SpringMVC响应

SpringMVC返回值类型

控制方法返回值为字符串


返回带有前缀的字符串:
转发:forward:/WEB-INF/views/index.jsp
重定向:redirect:/index.jsp

/**
 * 指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/pages/success.jsp
 */
@RequestMapping("/str")
public String respStr(User user,HttpSession session){
    System.out.println("aaaaaaaaaaaa");
    session.setAttribute("logined",user);
    return "success";
}

控制方法无返回值

Servlet原始API可以作为控制器中方法的参数,在controller方法形参上可以定义request和response,使用request或response指定响应结果:

1. 使用request转发跳转
/**
 * 返回值如果是void,则方法名称作为视图名称
 * 可以通过重定向和转发实现页面跳转
 *
 */
@RequestMapping("/void")
public void respStr(User user,  HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
    System.out.println("aaaaaaaaaaaa");
    request.setAttribute("logined",user);
    request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
}
2. 使用response重定向跳转

response.sendRedirect("testRetrunString")

需要注意的是 : 重定向不能访问到WEB-INF目录下的资源

/**
 * 返回值如果是void,则方法名称作为视图名称
 * 可以通过重定向和转发实现页面跳转
 */
@RequestMapping("/void")
public void respStr(User user,  HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
    //业务操作...
    response.sendRedirect(request.getContextPath()+"/index.jsp");
}
3. 使用response直接响应数据
/**
 * 返回值如果是void,则方法名称作为视图名称
 * 可以通过重定向和转发实现页面跳转
 */
@RequestMapping("/void")
public void respStr(User user,  HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
    //业务操作...
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/json;charset=utf-8");
    response.getWriter().write("json串");
}

控制方法返回ModelAndView

ModelAndView是SpringMVC为我们提供的一个对象,该对象也可以用作控制器方法的返回值。

他其中有二个常用方法:

方法名称 作用
addObject(String name,Object value) 向Model中设置值
setViewName(String viewName) 设置需要跳转的视图名称
/**
 * @return ModelAndView  可以设置数据与跳转视图
 */
@RequestMapping("/mv")
public ModelAndView mv(User user) throws ServletException, IOException {
    ModelAndView mv = new ModelAndView();
    //将数据保存到Model中
    mv.addObject("logined", user);
    //设置视图名称
    mv.setViewName("success");

    return mv;
}

SpringMVC页面跳转方式

controller方法在提供了String类型的返回值之后,默认就是请求转发。我们也可以写成:

转发跳转页面

/**
 * 返回值如果是void,则方法名称作为视图名称
 * 可以通过重定向和转发实现页面跳转
 */
@RequestMapping("/forward")
public String forward(User user,HttpSession session) throws ServletException, IOException {

    //将数据保存到session中
    session.setAttribute("logined", user);

    return "forward:/WEB-INF/pages/success.jsp";
}
需要注意的是,如果用了formward:则路径必须写成实际视图url,不能写逻辑视图。

它相当于“request.getRequestDispatcher("url").forward(request,response)”。

使用请求转发,既可以转发到jsp,也可以转发到其他的控制器方法。

重定向跳转页面

contrller方法提供了一个String类型返回值之后,它需要在返回值里使用:redirect:

/**
 * 返回值如果是void,则方法名称作为视图名称
 * 可以通过重定向和转发实现页面跳转
 */
@RequestMapping("/redirect")
public String redirect(User user,HttpSession session) throws ServletException, IOException {

    //将数据保存到session中
    session.setAttribute("logined", user);

    return "redirect:/index.jsp";
}

它相当于“response.sendRedirect(url)”。需要注意的是,如果是重定向到jsp页面,则jsp页面不能写在WEB-INF目录中,否则无法找到。

SpringMVC响应JSON格式数据

添加依赖

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

过滤静态资源

<!--配置资源目录,springMVC框架不拦截-->
<!--js目录下的所有资源不拦截-->
<mvc:resources mapping="/js/**" location="/js/**"></mvc:resources>
<!--imgs目录下的所有资源不拦截
<mvc:resources mapping="/imgs/**" location="/imgs/**"></mvc:resources>
-->
<!--css目录下的所有资源不拦截
<mvc:resources mapping="/css/**" location="/css/**"></mvc:resources>
-->
<!--开放资源的访问也可以这样配-->
<mvc:default-servlet-handler/>

发送异步请求

<h1>用户登录功能---异步ajax请求,响应json格式数据</h1>
<input id="btn" type="button" value="点击异步获取数据">

<script src="js/jquery-3.3.1.min.js"></script>
<script>
$(function(){
    $("#btn").click(function () {

        //发送异步请求
        var url = "${pageContext.request.contextPath}/response/json";
        var params = "{username:'zs',password:'123456'}";
        $.ajax({
            type:"POST",
            url: url,
            data: params,
            contentType:"application/json;charset=utf-8",
            dataType:"json",
            success: function(data){
              alert(data)
            }
        });

    })
})
</script>

响应JSON格式数据

/**
 * @RequestBody注解 可以将发送到服务器的json格式数据封装到参数中
 * @ResponseBody注解 可以将响应的对象转化为json格式数据响应给客户端
 * @param user
 * @return
 */
@RequestMapping("/json")
public @ResponseBody User json(@RequestBody User user){
    System.out.println(user);

    user.setUsername("张三");
    user.setPassword("456789");

    return user;
}
@RequestBody注解 可以将发送到服务器的json格式数据封装到参数中
@ResponseBody注解 可以将方法返回的对象转化为json格式数据响应给客户端

SpringMVC请求参数

参数绑定机制

1. 表单提交的数据都是k=v格式的 username=haha&password=123
2. SpringMVC的参数绑定过程是把表单提交的请求参数,作为控制器中方法的参数进行绑定的

参数绑定要求

1. 提交表单的name和参数的名称是相同的

支持的数据类型

1. 基本数据类型和字符串类型
2. 实体类型(JavaBean)
3. 集合数据类型(List、map集合等)

请求绑定基本数据类型和字符串

客户端

<h1>根据id查询用户</h1>
<a href="${pageContext.request.contextPath}/user/findById?id=1">根据id查询用户</a>

<h1>根据用户名和密码查询用户</h1>
<a href="${pageContext.request.contextPath}/user/findByUsername?username=aaa&password=123">根据id查询用户</a>

服务器

@RequestMapping("/user")
public class UserController {

    @RequestMapping(path = "/findById",params = {"id"})
    public  String findById(Integer id){
        System.out.println(id);
        System.out.println("查询所有用户....");
        return "success" ;
    }

    @RequestMapping(path = "/findByUsername")
    public  String findByUsername(String username,String password){
        System.out.println(username+" "+password);
        System.out.println("查询所有用户....");
        return "success" ;
    }
}

请求参数绑定实体类型

定义实体类

package com.itheima.bean;

public class User {
    private String username ;

    private String password ;

    private int age ;

    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 int getAge() {
        return age;
    }

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

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

客户端

<h1>添加用户</h1>
<form action="${pageContext.request.contextPath}/user/add">
    用户名: <input type="text" name="username"> <br>
    密&nbsp;&nbsp;码: <input type="password" name="password"><br>
    年&nbsp;&nbsp;龄: <input type="text" name="age"><br>
    <input type="submit" value="注册">
</form>

服务器

/**
 * @param user  封装数据的实体对象
 * @return
 */
@RequestMapping(value = "/add")
public  String add(User user){
    System.out.println(user);
    System.out.println("添加用户....");
    return "success" ;
}

注意:

  1. 提交表单的name和JavaBean中的属性名称需要一致
  2. JavaBean中的属性类型如果使用基本类型,如果没有该参数程序会报错

请求参数绑定List集合类型

创建实体类

public class Order {

    private String ono ;

    private Double money ;

    public String getOno() {
        return ono;
    }

    public void setOno(String ono) {
        this.ono = ono;
    }

    public Double getMoney() {
        return money;
    }

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

    @Override
    public String toString() {
        return "Order{" +
                "ono='" + ono + '\'' +
                ", money=" + money +
                '}';
    }
}

实体类型添加集合

[图片上传失败...(image-818d50-1700092477968)]

客户端

<h1>添加用户及订单</h1>
<form action="${pageContext.request.contextPath}/user/addWithOrders">
    用户名: <input type="text" name="username"> <br>
    密&nbsp;&nbsp;码: <input type="password" name="password"><br>
    年&nbsp;&nbsp;龄: <input type="text" name="age"><br>

    订单1编号: <input type="text" name="orders[0].ono"><br>
    订单1金额: <input type="text" name="orders[0].money"><br>

    订单2编号: <input type="text" name="orders[1].ono"><br>
    订单2金额: <input type="text" name="orders[1].money"><br>
    <input type="submit" value="注册">
</form>

服务端

@RequestMapping("/addWithOrders")
public  String addWithOrders(User user){
    System.out.println(user);
    System.out.println(user.getOrders());
    System.out.println("添加用户....");
    return "success" ;
}

请求参数绑定Map集合类型

客户端

<h1>添加用户及订单</h1>
<form action="${pageContext.request.contextPath}/user/addWithOthers">
    用户名: <input type="text" name="username"> <br>
    密&nbsp;&nbsp;码: <input type="password" name="password"><br>
    年&nbsp;&nbsp;龄: <input type="text" name="age"><br>

    订单1编号:<input type="text" name="others[o1].ono"><br>
    订单1金额: <input type="text" name="others[o1].money"><br>

    订单2编号:<input type="text" name="others[o2].ono"><br>
    订单2金额: <input type="text" name="others[o2].money"><br>
    <input type="submit" value="注册">
</form>

服务端

@RequestMapping("/addWithOthers")
public  String addWithOthers(User user){
    System.out.println(user);
    System.out.println(user.getOthers());
    System.out.println("添加用户....");
    return "success" ;
}

请求参数的中文乱码问题

如果请求参数中携带了中文会产生中文乱码问题,这个时候我们配置类乱码过滤器就可以解决POST方式的中文乱码问题.

tomcat7及以下版本需要手动解决中文乱码问题

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封装传递的参数有时候需要自己写一个类型转换器来实现

基本步骤

1. 创建一个类实现实现`Converter`接口
2. 实现`convert`方法,方法的参数就是传入的需要转换的数据,方法的返回值就是转换成功之后的数据
3. SpringMVC的配置文件中配置自定义转换器
4. 修改`<mvc:annotation-driven>`标签让自定义转换器生效

代码示例

1. 创建一个类实现实现Converter接口

public class DateConverter implements Converter<String,Date> {
    /**
     *
     * @param source  传入的需要转化的数据,例如:2018-01-01
     * @return  转化之后的数据
     */
    @Override
    public Date convert(String source) {

        return null;

    }
}

2. 实现convert方法,方法的参数就是传入的需要转换的数据,方法的返回值就是转换成功之后的数据

/**
 *
 * @param source  传入的需要转化的数据,例如:2018-01-01
 * @return  转化之后的数据
 */
@Override
public Date convert(String source) {
    if(source!=null){
        DateFormat df=new SimpleDateFormat("yyyy-MM-dd");
        try{
            //把字符串转为日期
            return df.parse(source);
        }catch (Exception e){
            new RuntimeException("数据类型转换失败!");
        }
    }else{
        System.out.println("请传入数据!");
    }
    return null;

}

3. SpringMVC的配置文件中配置自定义转换器

<!--配置自定义转换器-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <set>
            <bean class="com.itheima.convert.DateConverter"></bean>
        </set>
    </property>
</bean>

4. 修改<mvc:annotation-driven>标签让自定义转换器生效

<!--SpringMVC注解驱动-->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

获得原生servletAPI

Spring MVC支持使用原始ServletAPI对象作为控制器方法的参数进行注入, 常用的对象如下:

支持原始ServletAPI对象有:
    HttpServletRequest
    HttpServletResponse
    HttpSession
    InputStream
    OutputStream
    Reader
    Writer

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

[图片上传失败...(image-4809cf-1700092477968)]

SpringMVC常用注解

1. @RequestParam

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

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

客户端

<!-- requestParams注解的使用 -->
<a href="${pageContext.request.contextPath}/user/login2?name=aaa&password=123">requestParam注解</a>

服务端

@RequestMapping("/login2")
public  String login2(@RequestParam("name") String username, String password,@RequestParam(value = "age",required = false)Integer age){
    System.out.println(username+" "+password);
    System.out.println("用户登录....");
    return "success" ;
}

2. @RequestBody

作用: 用于获取请求体内容。直接使用得到是key=value&key=value...结构的数据。 get请求方式不适用。

属性:
  required:是否必须有请求体。默认值是:true。当取值为true时,get请求方式会报错。如果取值为false,get请求得到是null。

3. @PathVariable注解

作用
  用于绑定url中的占位符。例如:请求url中 /delete/{id},这个{id}就是url占位符。
  url支持占位符是spring3.0之后加入的。是springmvc支持rest风格URL的一个重要标志。

属性
  value:指定url中的占位符名称
  required:是否必须提供占位符。
restful风格的URL:请求路径一样,可以根据不同的请求方式去执行后台的不同方法
    1. 结构清晰
    2. 符合标准
    3. 易于理解
    4. 扩展方便

客户端

<h1>restfull</h1>
<a href="${pageContext.request.contextPath}/user/find/1">查询用户</a>

服务器

@RequestMapping("/find/{id}")
public  String find(@PathVariable("id") Integer id){
    System.out.println(id);
    return "success" ;
}

REST风格URL

Restful是一种软件架构风格、设计风格, 而不是标准, 只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。
Restful风格的请求是使用“url+请求方式”表示一次请求目的的, HTTP协议里面四个表示操作方式的动词如下:
GET:用于获取资源
POST:用于新建资源
PUT:用于更新资源
DELETE:用于删除资源
例如:
/user/1 GET:得到id=1的user
/user/1 DELETE:删除id=1的user
/user/1 PUT:更新id=1的user
/user   POST:新增user

上述url地址/user/1中的1就是要获得的请求参数, 在Spring MVC中可以使用占位符进行参数绑定。地址/user/1可以写成/user/{id} ,占位符{id} 对应的就是1的值。在业务方法中我们可以使用@PathVariable注解进行占位符的匹配获取操作。

4. @RequestHeader注解

作用: 用于获取请求消息头。
属性:
    value:提供消息头名称
    required:是否必须有此消息头 注: 在实际开发中一般不怎么用。

@RequestMapping("/headers")
public  String headers(@RequestHeader("User-Agent")String agent){
    System.out.println(agent);
    return "success" ;
}

5. @CookieValue注解

作用: 用于把指定cookie名称的值传入控制器方法参数。
属性:
  value:指定cookie的名称。
  required:是否必须有此cookie。
@RequestMapping("/cookies")
public  String cookies(@CookieValue("JSESSIONID")String sessionID){
    System.out.println(sessionID);
    return "success" ;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容