表单中请求参数都是基于key=value的。SpringMVC绑定请求参数的过程是通过把表单提交请求参数,作为控制器中方法参数进行绑定的。

如:

<a href="account/findAccount?accountId=10">查询账户</a>
@RequestMapping("/findAccount") 
public String findAccount(Integer accountId) {
       System.out.println("查询了账户。"+accountId); 
       return "success";
}

支持的数据类型:

  • 基本类型参数:包括基本类型和String类型
  • POJO类型参数:包括实体类,以及关联的实体类
  • 数组和集合类型参数:包括List结构和Map结构的集合(包括数组)

SpringMVC绑定请求参数是自动实现的,但是要想使用,必须遵循使用要求。

使用要求:

  • 基本类型参数:要求参数的名称必须和控制器中方法的形参名称保持一致。
  • POJO类型参数:要求表单中参数名称和POJO类的属性名称保持一致,并且控制器方法的参数类型必须是POJO类型。
  • 集合类型参数:第一种,要求集合类型请求参数必须是POJO中,在表单中请求参数名称要和POJO中集合属性名称相同。给List集合中的元素赋值,使用下标。给Map集合中的元素赋值,使用键值对;第二种,接收的请求参数是json格式数据,需要借助一个注解实现。

注意:自带的内置转换器可以实现一些数据类型自动转换。(org.springframework.core.convert.support)如遇特殊类型转换要求,需要自行定义类型转换器。

使用示例

一)基本类型和String类型作为参数

<fieldset>
    <h1>基本类型和String类型作为参数</h1>
    <a href="${pageContext.request.contextPath}/Account/find?accountId=2&accountName=张三">查询账户</a>
</fieldset>
@Controller
@RequestMapping("/Account")
public class AccountController {
    @RequestMapping(value = "/find")
    public ModelAndView findAccount(Integer accountId,String accountName){
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.addObject("message","账户信息"+accountId+"/"+accountName);
        modelAndView.setViewName("success");
        return modelAndView;
    }
}

二)POJO类型作为参数

public class Account {
    private Integer accountId;
    private String accountName;
    private float money;
    private Address address;

    @Override
    public String toString() {
        return "Account{" +
                "accountId=" + accountId +
                ", accountName='" + accountName + '\'' +
                ", money=" + money +
                ", address=" + address +
                '}';
    }

    public Integer getAccountId() {
        return accountId;
    }

    public void setAccountId(Integer accountId) {
        this.accountId = accountId;
    }

    public String getAccountName() {
        return accountName;
    }

    public void setAccountName(String accountName) {
        this.accountName = accountName;
    }

    public float getMoney() {
        return money;
    }

    public void setMoney(float money) {
        this.money = money;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}
public class Address implements Serializable {
    private String provinceName;
    private String cityName;

    @Override
    public String toString() {
        return "Address{" +
                "provinceName='" + provinceName + '\'' +
                ", cityName='" + cityName + '\'' +
                '}';
    }

    public String getProvinceName() {
        return provinceName;
    }

    public void setProvinceName(String provinceName) {
        this.provinceName = provinceName;
    }

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }
}
<fieldset>
    <h1>POJO类型作为参数</h1>
    <form method="post" action="${pageContext.request.contextPath}/Account/saveAccount">
        账户:<input name="accountName" type="text"><br>
        资金:<input name="money" type="text"><br>
        省份:<input name="address.provinceName" type="text"><br>
        城市:<input name="address.cityName" type="text"><br>
        <input type="submit" value="保存"/>
    </form>
</fieldset>
    @RequestMapping("/saveAccount")
    public ModelAndView saveAccount(Account account){
        System.out.println(account);
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.addObject("message",account);
        modelAndView.setViewName("success");
        return modelAndView;
    }

三)数组和集合类型参数

public class User implements Serializable {
    private String username;
    private String password;
    private Integer age;
    private List<Account> accounts;
    private Map<String,Account> accountMap;

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", accounts=" + accounts +
                ", accountMap=" + accountMap +
                '}';
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

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

    public List<Account> getAccounts() {
        return accounts;
    }

    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }

    public Map<String, Account> getAccountMap() {
        return accountMap;
    }

    public void setAccountMap(Map<String, Account> accountMap) {
        this.accountMap = accountMap;
    }
}
<fieldset>
    <h1>数组和集合类型作为参数</h1>
    <form action="${pageContext.request.contextPath}/user/updateUser" method="post">
        用户名:<input name="username" type="text"><br>
        密码:<input name="password" type="text"><br>
        年龄:<input name="age" type="text"><br>
        账户:<input name="accounts[0].accountName" type="text"><br>
        资金:<input name="accounts[0].money" type="text"><br>
        账户:<input name="accounts[1].accountName" type="text"><br>
        资金:<input name="accounts[1].money" type="text"><br>
        账户:<input name="accountMap['one'].accountName" type="text"><br>
        资金:<input name="accountMap['one'].money" type="text"><br>
        账户:<input name="accountMap['two'].accountName" type="text"><br>
        资金:<input name="accountMap['two'].money" type="text"><br>
        <input type="submit" value="保存">
    </form>
</fieldset>
@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/updateUser")
    public ModelAndView updateUser(User user){
        System.out.println(user);
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("success");
        modelAndView.addObject("message",user);
        return modelAndView;
    }
}

 

请求参数乱码问题

post请求方式

在web.xml中配置一个过滤器

    <!--配置SpringMVC编码过滤器-->
    <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>
        <!--启动过滤器-->
        <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>

springMVC配置文件中可以配置,静态资源不过滤:

<!--location表示路径,mapping表示文件,
**表示该目录下的文件以及子目录的文件-->
<mvc:resources location="/css/" mapping="/css/**"/>
<mvc:resources location="/images/" mapping="/images/**"/> 
<mvc:resources location="/scripts/" mapping="/javascript/**"/>

get请求方式

       tomcat对GET和POST请求方式是不同的,GET请求的编码问题,要改tomcat的server.xml配置文件。

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
<!--改为-->
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" useBodyEncodingForURI="true"/>

如果遇到ajax请求仍然乱码,请把useBodyEncodingForURI="true"改为URIEncoding="UTF-8"即可。

 

RequestParam注解实现参数绑定

作用:把请求中指定名称的参数给控制器中的形参赋值。

属性:

  • value:请求参数中的名称。
  • required:请求参数中是否必须提供此参数。默认值:true,表示必须提供,如果不提供将报错。

使用示例

<fieldset>
    <h1>RequestParam注解参数绑定</h1>
    <a href="${pageContext.request.contextPath}/user/saveUser?name=张三">保存用户</a>
</fieldset>
    @RequestMapping("/saveUser")
    public ModelAndView saveUser(@RequestParam("name") String username,@RequestParam(value = "age",required = false) Integer age){
        System.out.println(username+" "+age);
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("success");
        modelAndView.addObject("message",username+":"+age);
        return modelAndView;
    }

当url中没有传age参数时,不会报错。

 

自定义类型转换器

使用示例

<fieldset>
    <h1>自定义类型转换器</h1>
    <a href="${pageContext.request.contextPath}/user/getUser?date=2018-01-10">获取用户</a>
</fieldset>

当控制器中的方法使用String去接收请求中的参数时是没有问题的。

    @RequestMapping("/getUser")
    public ModelAndView getUser(String date){
        System.out.println(date);
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("success");
        modelAndView.addObject("message",date);
        return modelAndView;
    }

而此时控制器中的方法使用Date去接收请求中的参数时就会报错。

    @RequestMapping("/getUser")
    public ModelAndView getUser(Date date){
        System.out.println(date);
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.setViewName("success");
        modelAndView.addObject("message",date);
        return modelAndView;
    }

 第一步:定义一个类,实现Converter接口。

public class StringToDateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
        DateFormat format=null;
        try {
            if(s==null||s.isEmpty()){
                throw new NullPointerException("输入字符串为空");
            }
            format=new SimpleDateFormat("yyyy-MM-dd");
            Date date = format.parse(s);
            return date;
        } catch (Exception e) {
            throw new RuntimeException("输入日期有误");
        }
    }
}

第二步:在spring配置文件中配置类型转换器。spring配置类型转换器的机制是,将自定义的转换器注册到类型转换器服务中去。

    <!--配置类型转换器工厂-->
    <bean id="conversionService2" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <!--给工厂注入一个新的类型转换器-->
        <property name="converters">
            <array>
                <!--配置自定义类型转换器-->
                <bean class="com.company.utils.StringToDateConverter"></bean>
            </array>            
        </property>
    </bean>

第三步:在spring配置文件中,在annotation-driven标签中引用配置的类型转换服务。

    <!--引用自定义类型转换器-->
    <mvc:annotation-driven conversion-service="conversionService2"></mvc:annotation-driven>

 

使用ServletAPI对象作为方法参数

SpringMVC还支持使用原始ServletAPI对象作为控制器方法的参数。支持原始ServletAPI对象有:

  • HttpServletRequest
  • HttpServletResponse
  • HttpSession
  • java.security.Principal
  • Locale
  • InputStream
  • OutputStream
  • Reader
  • Writer

可以把上述对象,直接写在控制的方法参数中使用。

<fieldset>
    <h1>ServletAPI作为参数</h1>
    <a href="${pageContext.request.contextPath}/user/testServletAPI">test servlet api</a>
</fieldset>
    @RequestMapping("/testServletAPI")
    public String testServletAPI(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, HttpSession httpSession){
        System.out.println(httpServletRequest);
        System.out.println(httpServletResponse);
        System.out.println(httpSession);
        return "success";
    }

 

消息头相关的两个注解

RequestHeader

作用:用于获取请求消息头。

属性:

  • value:提供消息头名称
  • required:是否必须有此消息头

注:在实际开发中一般不怎么用。

<fieldset>
    <h1>RequestHeader注解</h1>
    <a href="${pageContext.request.contextPath}/user/useRequestHeader">use Request Header</a>
</fieldset>
    @RequestMapping("/useRequestHeader")
    public String useRequestHeader(@RequestHeader(value = "Accept-Language",required = false)String requestHeader){
        System.out.println(requestHeader);
        return "success";
    }

CookieValue

作用:用于把指定cookie名称的值传入控制器方法参数。

属性:

  • value:指定cookie的名称。
  • required:是否必须有此cookie。
<fieldset>
    <h1>CookieValue注解</h1>
    <a href="${pageContext.request.contextPath}/user/useCookieValue">use Cookie Value</a>
</fieldset>
    @RequestMapping("/useCookieValue")
    public String useCookieValue(@CookieValue(value = "JSESSIONID",required = false) String cookieValue){
        System.out.println(cookieValue);
        return "success";
    }

 

 posted on 2019-11-25 22:12  会飞的金鱼  阅读(121)  评论(0)    收藏  举报