SpringMVC基础知识(2)

1、SpringMVC对请求参数的处理

  在之前的servlet中我们可以通过request.getParameter()来获取请求中的参数,但是在我们编写的SpringMVC的应用程序中,在具体请求的方法中并不包含request参数,

  需要使用以下几个注解:

    @RequestParam:获取请求的参数

    @RequestHeader:获取请求头信息

    @CookieValue:获取cookie中的值

  @RequestParam的基本使用

package com.llxazy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class RequestController {

    /**
     * 如何获取SpringMVC中请求中的信息
     *  默认情况下,可以直接在方法的参数中填写跟请求一样的名称,此时会默认接受参数
     *      如果有值,直接赋值,如果没有,那么直接给空值
     *
     * @RequestParam:获取请求中的参数值,使用此注解之后,参数的名称不需要跟请求的名称一致,但是必须要写
     *      public String request(@RequestParam("user") String username){
     *
     *      此注解还包含三个参数:
     *      value:表示要获取的参数值
     *      required:表示此参数是否必须,默认是true,如果不写参数那么会报错,如果值为false,那么不写参数不会有任何错误
     *      defaultValue:如果在使用的时候没有传递参数,那么定义默认值即可
     * @param username
     * @return
     */
    @RequestMapping("/request")
    public String request(@RequestParam(value = "user",required = false,defaultValue = "hehe") String username){
        System.out.println(username);
        return "success";
    }
}

  @RequestHeader的基本使用:

package com.llxazy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import sun.management.resources.agent;

@Controller
public class RequestController {

    /**
     * 如果需要获取请求头信息该如何处理呢?
     *  可以使用@RequestHeader注解,
     *      public String header(@RequestHeader("User-Agent") String agent){
     *      相当于  request.getHeader("User-Agent")
     *
     *      如果要获取请求头中没有的信息,那么此时会报错,同样,此注解中也包含三个参数,跟@RequestParam一样
     *          value
     *          required
     *          defalutValue
     * @param agent
     * @return
     */
    @RequestMapping("/header")
    public String header(@RequestHeader("User-Agent") String agent){
        System.out.println(agent);
        return "success";
    }
}

  @CookieValue的基本使用

package com.llxazy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import sun.management.resources.agent;

@Controller
public class RequestController {

    /**
     * 如果需要获取cookie信息该如何处理呢?
     *  可以使用@CookieValue注解,
     *      public String cookie(@CookieValue("JSESSIONID") String id){
     *      相当于
     *      Cookie[] cookies = request.getCookies();
     *      for(Cookie cookie : cookies){
     *          cookie.getValue();
     *      }
     *      如果要获取cookie中没有的信息,那么此时会报错,同样,此注解中也包含三个参数,跟@RequestParam一样
     *          value
     *          required
     *          defalutValue
     * @param id
     * @return
     */
    @RequestMapping("/cookie")
    public String cookie(@CookieValue("JSESSIONID") String id){
        System.out.println(id);
        return "success";
    }
}

  在SpringMVC的控制中,能直接完成对象的属性赋值操作,不需要人为干预。

  User.java

package com.llxazy.bean;

import java.util.Date;

public class User {
    private Integer id;
    private String name;
    private Integer age;
    private Date date;
    private Address address;

   //省略get/set/toString方法
}

  Address.java

package com.llxazy.bean;

public class Address {
    private String province;
    private String city;
    private String town;
  //省略get/set/toString方法
}

  login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="addUser" method="post">
    编号:<input type="text" name="id"/><br>
    姓名:<input type="text" name="name"/><br>
    年龄:<input type="text" name="age"/><br>
    日期:<input type="text" name="date"/><br>
    省份:<input type="text" name="address.province"/><br>
    城市:<input type="text" name="address.city"/><br>
    区域:<input type="text" name="address.town"/><br>
    <input type="submit" value="submit"/><br>
</form>
</body>
</html>

  UserController.java

package com.llxazy.controller;

import com.llxazy.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserController {

    @RequestMapping("/addUser")
    public String addUser(User user){
        System.out.println(user);
        return "success";
    }
}

 

2、乱码问题的解决

    我们在表单或者发送请求的时候,经常会遇到中文乱码的问题,那么如何解决乱码问题呢?

    GET请求:在server.xml文件中,添加URIEncoding=“UTF-8”

    POST请求:web.xml中编写过滤器进行实现

      注意:如果配置了多个过滤器,那么字符编码过滤器一定要在最前面,否则失效。

  <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <!--解决post请求乱码-->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!--解决响应乱码-->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 

3、SpringMVC对原生API的支持

package com.llxazy.controller;

import com.llxazy.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.PrintWriter;

@Controller
public class UserController {

    @RequestMapping("/addUser")
    public String addUser(User user){
        System.out.println(user);
        return "success";
    }

    /**
     * SpringMVC也可以在参数上使用原生的Servlet API
     *
     *  HttpSession
     *  HttpServletRequest
     *  HttpServletResponse
     *
     *  java.security.Principal 安全协议相关
     *  Locale:国际化相关的区域信息对象
     *  InputStream:
     *      ServletInputStream inputStream = request.getInputStream();
     *  OutputStream:
     *      ServletOutputStream outputStream = response.getOutputStream();
     *  Reader:
     *      BufferedReader reader = request.getReader();
     *  Writer:
     *      PrintWriter writer = response.getWriter();
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("api")
    public String api(HttpSession session, HttpServletRequest request, HttpServletResponse response){
        request.setAttribute("requestParam","request");
        session.setAttribute("sessionParam","session");
        return "success";
    }
}

 

4、使用Model,Map,ModelMap传输数据到页面

  

package com.llxazy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Map;

@Controller
public class OutputController {

    @RequestMapping("output1")
    public String output1(Model model){
        model.addAttribute("msg","hello,Springmvc");
        return "output";
    }

    @RequestMapping("output2")
    public String output2(ModelMap model){
        model.addAttribute("msg","hello,Springmvc");
        return "output";
    }

    @RequestMapping("output3")
    public String output1(Map map){
        map.put("msg","hello,Springmvc");
        return "output";
    }
}

 

5、使用ModelAndView对象传输数据到页面

package com.llxazy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class OutputController {

    @RequestMapping("mv")
    public ModelAndView mv(){
        ModelAndView mv = new ModelAndView();
        mv.setViewName("output");
        mv.addObject("msg","hello.modelAndView");
        return mv;
    }
}

  发现当使用modelAndView对象的时候,返回值的类型也是此对象,可以将要跳转的页面设置成view的名称,来完成跳转的功能,同时数据也是放到request作用中。

 

6、使用session传输数据到页面

  @SessionAttribute:此注解可以表示,当向request作用域设置数据的时候同时也要向session中保存一份,此注解有两个参数,一个value(表示将哪些值设置到session中),另外一个type(表示按照类型来设置数据,一般不用,因为有可能会将很多数据都设置到session中,导致session异常)。

@Controller
@SessionAttributes(value = "msg")
public class OutputController {

    @RequestMapping("output1")
    public String output1(Model model){
        model.addAttribute("msg","hello,Springmvc");
        System.out.println(model.getClass());
        return "output";
    }
}

 

7、使用@ModelAttribute来获取请求中的数据

  @ModelAttribute注解用于将方法的参数或者方法的返回值绑定到指定的模型属性上,并返回给web视图。首先来介绍一个业务场景,来帮助大家做理解,在实际工作中,有些时候我们在修改数据的时候可能只需要修改其中几个字段,而不是全部的属性字段都获取,那么当提交属性的时候,从form表单中获取的数据就有可能只包含了部分属性,此时再向数据库更新的时候,肯定会丢失属性,因为对象的封装是springmvc自动帮我们new的,所以此时需要先将从数据库获取的对象保存下来,当提交的时候不是new新的对象,而是在原来的对象上进行属性覆盖,此时就需要使用@ModelAttribute注解。

  User.java

package com.llxazy.bean;

public class User {
    private Integer id;
    private String name;
    private String password;
    private Integer age;
  //省略get/set/toString  
}

  如果添加的@ModelAttribute(“”)属性的值不对,那么也是获取不到值的。同时可以添加@SessionAttributes属性,但是注意,如果没有设置值的话,会报错

  UserController.java

package com.llxazy.controller;

import com.llxazy.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@SessionAttributes("u")
public class UserController { Object o1 = null; Object o2 = null; Object o3 = null; @RequestMapping("update") public String update(@ModelAttribute("user") User user,Model model){ System.out.println(user); o2 = model; //可以看到所有的model都是同一个对象 System.out.println(o1==o2); //可以看到存储的user对象也是同一个 System.out.println(user == o3); return "output"; } @ModelAttribute public void MyModelAttribute(Model model){ o1 = model; User user = new User(); user.setId(1); user.setName("张三"); user.setAge(12); user.setPassword("123"); model.addAttribute("user",user); System.out.println("modelAttribute:"+user); o3 = user; } }

  index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <form action="update" method="post">
    <input type="hidden" value="1" name="id">
    姓名:李四<br>
    密码:<input type="text" name="password"><br>
    年龄:<input type="text" name="age"><br>
    <input type="submit" value="提交">
  </form>
  </body>
</html>

  其实在使用的时候可以简化写法,也就是说,在方法的参数上不加@ModelAttribute也不会有问题

  @RequestMapping("update")
    public String update(User user,Model model){
        System.out.println(user);
        o2 = model;
        //可以看到所有的model都是同一个对象
        System.out.println(o1==o2);
        //可以看到存储的user对象也是同一个
        System.out.println(user == o3);
        return "output";
    }

  注意:ModelAttribute除了可以使用设置值到model中之外,还可以利用返回值。

package com.llxazy.controller;

import com.llxazy.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;

@Controller
public class UserController {

    Object o1 = null;
    Object o2 = null;
    Object o3 = null;

    @RequestMapping("update")
    public String update(@ModelAttribute("u") User user,Model model){
        System.out.println(user);
        o2 = model;
        //可以看到所有的model都是同一个对象
        System.out.println(o1==o2);
        //可以看到存储的user对象也是同一个
        System.out.println(user == o3);
        return "output";
    }

    @ModelAttribute("u")
    public User MyModelAttribute(Model model){
        o1 = model;
        User user = new User();
        user.setId(1);
        user.setName("张三");
        user.setAge(12);
        user.setPassword("123");
//        model.addAttribute("user",user);
        System.out.println("modelAttribute:"+user);
        o3 = user;
        return user;
    }
}

  总结:通过给参数赋值能够发现,当给方法中的参数设置值的时候,如果添加了@ModelAttribute注解,那么在查找值的时候,是遵循以下方式:

    1、方法的参数使用参数的类型首字母小写,或者使用@ModelAttribute("")的值

    2、先看之前是否在model中设置过该属性值,如果设置过就直接获取

    3、看@SessionAttributes注解标注类中的方法是否给session中赋值,如果有的话,也是直接获取,没有报异常

 

8、使用forward实现页面转发

  在发送请求的时候,可以通过forward:来实现转发的功能:

package com.llxazy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class ForWardController {

    /**
     * 当使用转发的时候可以添加前缀forward:index.jsp,此时是不会经过视图解析器的,所以要添加完整的名称
     * forward:也可以由一个请求跳转到另外一个请求
     * @return
     */
    @RequestMapping("/forward01")
    public String forward(){
        System.out.println("1");
        return "forward:/index.jsp";
    }

    @RequestMapping("/forward02")
    public String forward2(){
        System.out.println("2");
        return "forward:/forward01";
    }
}

 

9、使用redirect来实现重定向

package com.llxazy.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class RedirectController {

    /**
     * redirect :重定向的路径
     *      相当于 response.sendRedirect("index.jsp")
     *      跟视图解析器无关
     * @return
     */
    @RequestMapping("redirect")
    public String redirect(){
        System.out.println("redirect");
        return "redirect:/index.jsp";
    }

    @RequestMapping("/redirect2")
    public String redirect2(){
        System.out.println("redirect2");
        return "redirect:/redirect";
    }
}

 

重定向和转发的区别:  

  转发:

    由服务器的页面进行跳转,不需要客户端重新发送请求:

    特点如下:

      1、地址栏的请求不会发生变化,显示的还是第一次请求的地址

      2、请求的次数,有且仅有一次请求

      3、请求域中的数据不会丢失

      4、根目录:localhost:8080/项目地址/,包含了项目的访问地址

                    

 

  重定向:

    在浏览器端进行页面的跳转,需要发送两次请求(第一次是人为的,第二次是自动的)

    特点如下:

      1、地址栏的地址发生变化,显示最新发送请求的地址

      2、请求次数:2次

      3、请求域中的数据会丢失,因为是不同的请求

      4、根目录:localhost:8080/ 不包含项目的名称

                    

                   对比:

区别转发forward()重定向sendRedirect()
根目录 包含项目访问地址 没有项目访问地址
地址栏 不会发生变化 会发生变化
哪里跳转 服务器端进行的跳转 浏览器端进行的跳转
请求域中数据 不会丢失 会丢失

10、静态资源的访问

<body>
  hello springmvc
  <img src="${ctx}/images/timg.jpg">
</body>

发现此时是找不到对应的mapping映射的,是因为DispatcherServlet会拦截所有的请求,而此时我们没有对应图片的请求处理方法,所以报错了,想要解决的话非常简单,只需要添加如下配置即可

<!--
此配置表示  我们自己配置的请求由controller来处理,但是不能请求的处理交由tomcat来处理
静态资源可以访问,但是动态请求无法访问
-->
<mvc:default-servlet-handler/>
<!--保证静态资源和动态请求都能够访问-->
<mvc:annotation-driven/>

 

 

 

posted @ 2021-07-08 17:43  禾野牧村  阅读(64)  评论(0)    收藏  举报