SpringMVC简介及实用接收请求方式

2021-03-26  本文已影响0人  写程序踩过的坑

SpringMVC简介及实用接收请求方式

什么是MVC?

在 JavaEE 开发中,几乎全都是基于 B/S (浏览器服务器)架构的开发。那么在 B/S 架构中,系统标准的三层架构包括:表现层、业务层、持久层。而MVC在表现层!

SpringMVC

全名叫 Spring Web MVC,是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级

Web 框架,属于 SpringFrameWork 的后续产品。

Spring MVC和Struts2一样,都是 为了解决表现层问题 的web框架,它们都是基于 MVC 设计模

式的。这些表现层框架的主要职责就是处理前端HTTP请求。

作用:

1)接收请求

2)返回响应,跳转页面

RESTful风格

REST(Representational State Transfer)

Restful 的优点:它结构清晰、符合标准、易于理解、扩展⽅便。

原有的url设计

localhost:8080/user/queryUserById.action?id=3

有了RESTful 变成:

http://localhost:8080/user/3

RESTful风格即使请求路径相同,但状态操作(get,post,put,delete)不同,都可以请求到想要的接口。

通过项目讲解

一 springmvc-demo

1 传参方式和后台接

请求参数绑定:说白了SpringMVC如何接收请求参数?

原servlet接收一个整型参数:

1)String ageStr = request.getParameter("age");

2) Integer age = Integer.parseInt(ageStr);

SpringMVC框架对Servlet的封装,简化了servlet的很多操作

SpringMVC在接收整型参数的时候,直接在Handler方法中声明形参即可

@RequestMapping("xxx")

public String handle(Integer age) {

System.out.println(age);

}

注意:

1 参数绑定:取出参数值绑定到handler方法的形参上,传递的参数名和声明的形参名称保持一致

2 对于布尔类型(Boolean)的参数, 请求的参数值只接收true或false,或者1或0

方法参数名和传递参数名不一致呢?

可以使用@RequestParam注解,如

 /*
     * SpringMVC 接收简单数据类型参数  url:/demo/handle03?id=1
     *
     * 注意:接收简单数据类型参数,直接在handler方法的形参中声明即可,框架会取出参数值然后绑定到对应参数上
     * 要求:传递的参数名和声明的形参名称保持一致
     */
    @RequestMapping("/handle03")
    public ModelAndView handle03(@RequestParam("ids") Integer id,Boolean flag) {

        Date date = new Date();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("date",date);
        modelAndView.setViewName("success");
        return modelAndView;
    }

建议:使用包装类型,因为基础数据类型不可以为null

@RequestMapping(value = "/handle/{id}",method ={RequestMethod.GET})

public ModelAndView handleGet(@PathVariable("id") Integer id) {

}

1 接收pojo类型参数,直接形参声明即可,类型就是Pojo的类型,形参名无所谓

2 但是要求传递的参数名必须和Pojo的属性名保持一致

前端代码

测试用例:SpringMVC接收pojo类型参数

<a href="/demo/handle04?id=1&amp;name=zhangsan">点击测试</a>

后台 (注意:这里要加get set方法)

public class User {

    private Integer id;
    
    private String name;
    
    }
    
    public ModelAndView handle04(User user) {
    
    Date date = new Date();
    
    ModelAndView modelAndView = new ModelAndView();
    
    modelAndView.addObject("date",date);
    
    modelAndView.setViewName("success");
    
    return modelAndView;

}

前端代码

测试用例:SpringMVC接收pojo包装类型参数

<a href="/demo/handle05?user.id=1&amp;user.name=zhangsan">点击测试</a>

后台(注意:这里要加get set方法)

public class QueryVo {

    private String mail;
    
    private String phone;
    
    // 嵌套了另外的Pojo对象
    
    private User user;

}

/\*

* SpringMVC接收pojo包装类型参数 url:/demo/handle05?user.id=1&user.username=zhangsan
* 不管包装Pojo与否,它首先是一个pojo,那么就可以按照上述pojo的要求来
* 1、绑定时候直接形参声明即可
* 2、传参参数名和pojo属性保持一致,如果不能够定位数据项,那么通过属性名 + "." 的方式进一步锁定数据
*

\*/

@RequestMapping("/handle05")

public ModelAndView handle05(QueryVo queryVo) {

    Date date = new Date();
    
    ModelAndView modelAndView = new ModelAndView();
    
    modelAndView.addObject("date",date);
    
    modelAndView.setViewName("success");
    
    return modelAndView;

}

用Ajax Json交互

1)前端到后台:前端ajax发送json格式字符串,后台直接接收为pojo参数,使用注解@RequstBody

2)后台到前端:后台直接返回pojo对象,前端直接接收为json对象或者字符串,使用注解

@ResponseBod

Spring MVC 使用 Json 交互所需jar包

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

前端jsp及js代码
<h2>Ajax json交互
</h2>

 $(function () {
            $("#ajaxBtn").bind("click",function () {
                // 发送ajax请求
                $.ajax({
                    url: '/demo/handle07',
                    type: 'POST',
                    data: '{"id":"1","name":"李四"}',
                    contentType: 'application/json;charset=utf-8',
                    dataType: 'json',
                    success: function (data) {
                        alert(data.name);
                    }
                })
            })
        })

后台controller代码

@RequestMapping("/handle07")

// 添加@ResponseBody之后,不再⾛视图解析器那个流程,⽽是等同于response直接输出

数据

public @ResponseBody User handle07(@RequestBody User user) {

    // 业务逻辑处理,修改name为张三丰

    user.setName("张三丰");

    return user;

}

文件上传

原生servlet处理上传的文件数据的,springmvc是对serlvet的封装

所需jar包

<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>

1.3.1

配置文件上传解析器
前端form

 <div>
        <h2>multipart 文件上传</h2>
        <fieldset>
            <%--
                1 method="post"
                2 enctype="multipart/form-data"
                3 type="file"
            --%>
            <form method="post" enctype="multipart/form-data" action="/demo/upload">
                <input type="file" name="uploadFile"/>
                <input type="submit" value="上传"/>
            </form>
        </fieldset>
    </div>

注意
1 method="post" 必须是post
2 enctype="multipart/form-data"
3 type="file"

后台接收Handler

  /**
     * 文件上传
     * @return
     */
    @RequestMapping(value = "/upload")
    public ModelAndView upload(MultipartFile uploadFile,HttpSession session) throws IOException {

        // 处理上传文件
        // 重命名,原名123.jpg ,获取后缀
        String originalFilename = uploadFile.getOriginalFilename();// 原始名称
        // 扩展名  jpg
        String ext = originalFilename.substring(originalFilename.lastIndexOf(".") + 1, originalFilename.length());
        String newName = UUID.randomUUID().toString() + "." + ext;

        // 存储,要存储到指定的文件夹,/uploads/yyyy-MM-dd,考虑文件过多的情况按照日期,生成一个子文件夹
        String realPath = session.getServletContext().getRealPath("/uploads");
        String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        File folder = new File(realPath + "/" + datePath);

        if(!folder.exists()) {
            folder.mkdirs();
        }


        // 存储文件到目录
        uploadFile.transferTo(new File(folder,newName));


        // TODO 文件磁盘路径要更新到数据库字段

        Date date = new Date();
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("date",date);
        modelAndView.setViewName("success");
        return modelAndView;
    }

重定向时请求参数会丢失,我们往往需要重新携带请求参数,我们可以进行动参数拼接如下:

return "redirect:handle01?name=" + name;

但是上述拼接参数的方法属于get请求,携带参数长度有限制,参数安全性也不够,此时,我们可以使用SpringMVC提供的flash属性机制,向上下行中添加flash属性,框架会在session中记录该属性值,当跳转到之后框架会自动删除flash属性,不需要我们手动删除,通过这种方式进行重定向参数传递,参数长度和安全性都得到了保障,如下:

/**
* SpringMVC 重定向时参数传递的问题
* 转发:A 找 B 借钱400,B没有钱但是悄悄的找到C借了400块钱给A
* url不会变,参数也不会丢失,一个请求
* 重定向:A 找 B 借钱400,B 说我没有钱,你找别人借去,那么A 又带着400块的借钱需求找到C
* url会变,参数会丢失需要重新携带参数,两个请求
*/

@RequestMapping("/handleRedirect")
public String handleRedirect(String name,RedirectAttributes redirectAttributes) {

    //return "redirect:handle01?name=" + name;  // 拼接参数安全性、参数长度都有局限
    // addFlashAttribute方法设置了一个flash类型属性,该属性会被暂存到session中,在跳转到页面之后该属性销毁
    redirectAttributes.addFlashAttribute("name",name);
    return "redirect:handle01";

}

SpringMVC在handler方法也可以传入Map、Model和ModelMap参数,并向这些参数中保存数据(放入到请求域),都可以在页面获取到。

eg:

@RequestMapping("/handle11")

public String handle11(ModelMap modelMap) {

}

它们之间是什么关系?

上一篇下一篇

猜你喜欢

热点阅读