SpringMvc 02

本文详细介绍了Spring MVC中ModelAttribute和SessionAttribute的使用,包括基于POJO属性和Map的示例。同时,讲解了Restful风格URL的概念、优点和PathVariable注解的应用。此外,还涵盖了控制器方法的返回值处理、JSON数据交互、文件上传(传统与跨服务器方式)及异常处理的实现步骤和案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第1章 ModelAttribute 和SessionAttribute[应用]

1.1 ModelAttribute

1.1.1 使用说明

在这里插入图片描述
在这里插入图片描述

1.1.2 使用示例

基于 POJO 属性的基本使用:

在这里插入图片描述
在这里插入图片描述

基于 Map 的应用场景示例 1: ModelAttribute 修饰方法带返回值

在这里插入图片描述
在这里插入图片描述

基于 Map 的应用场景示例 1: ModelAttribute 修饰方法不带返回值

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.2 SessionAttribute

1.2.1 使用说明

在这里插入图片描述

1.2.2 使用示例

在这里插入图片描述

tips SpringMvc匹配路径问题

不能写/*,因为/*目录匹配,一旦访问jsp页面,/*优先级高,DispatcherServlet没法处理,
写/同理,所以需要写放行路径,tomcat里两个默认servlet,jsp和default,在default里写
放行静态资源,jsp由专门servlet处理
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!--
      绝对不允许写/*
      在tomcat匹配过程中
      精确匹配 目录匹配 后缀名 /匹配

      但是写/ 也出问题

      然后去补上静态访问 添加给我默认servlet
  -->
  <servlet-mapping>
    <!--  所放行的类型    -->
    <servlet-name>default</servlet-name>
    <url-pattern>*.html</url-pattern>
    <url-pattern>*.css</url-pattern>
    <url-pattern>*.js</url-pattern>
    <url-pattern>*.png</url-pattern>
    <url-pattern>*.jpg</url-pattern>
  </servlet-mapping>

第2章 Restful 风格的 URL[应用]

2.1 概述

2.1.1 什么是 rest:

REST(英文: Representational State Transfer,简称 REST)描述了一个架构样式的网络系统,比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。在目前主流的三种 Web 服务交互方案中, REST 相比于 SOAP(Simple Object Access protocol,简单对象访问协议)以及 XML-RPC 更加简单明了,无论是对 URL 的处理还是对 Payload 的编码, REST 都倾向于用更加简单轻量的方法设计和实现。值得注意的是 REST 并没有一个明确的标准,而更像是一种设计的风格。
它本身并没有什么实用性,其核心价值在于如何设计出符合 REST 风格的网络接口。

2.1.2 restful 的优点

它结构清晰、符合标准、易于理解、 扩展方便,所以正得到越来越多网站的采用。
在这里插入图片描述

2.2 PathVaribale 注解在 rest 风格 url 中的应用

2.2.1 使用说明

在这里插入图片描述

2.2.2 使用示例

在这里插入图片描述

2.3 基于 HiddentHttpMethodFilter 的示例

    <!--
        过滤器的作用
        用来观察 你是携带了 名字叫做_method参数  根据你的需要将当前方式 改掉
    -->
    <filter>
        <filter-name>hiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>
	<!--  隐藏网站方法的过滤器    -->
    <filter-mapping>
        <filter-name>hiddenHttpMethodFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实际案例

控制层

@Controller
public class UserController {
    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    @ResponseBody
    public User findById(@PathVariable("id") int id){
        //mock查询
        User user = new User();
        user.setId(id);
        user.setUsername("小j");
        user.setPassword("123");
        user.setAge(18);
        return user;
    }
    @RequestMapping(value = "/user",method = RequestMethod.GET)
    @ResponseBody
    public List<Object> findAll(){
        //mock查询
        User user1 = new User();
        user1.setId(1);
        user1.setUsername("小h");
        user1.setPassword("123");
        user1.setAge(18);
        User user2 = new User();
        user2.setId(2);
        user2.setUsername("小蓝");
        user2.setPassword("123");
        user2.setAge(18);
        ArrayList<Object> users = new ArrayList<>();
        users.add(user1);
        users.add(user2);

        return users;
    }
    @RequestMapping(value = "/user/{id}",method = RequestMethod.POST)
    @ResponseBody
    public String update(@PathVariable("id") int id,User user){
        //mock更新

        System.out.println(id);
        System.out.println(user);


        return "success";
    }
    @RequestMapping(value = "/user",method = RequestMethod.PUT)
    @ResponseBody
    public String save(User user){
        //mock添加

        System.out.println(user);
       return "success";
    }
    @RequestMapping(value = "/user/{id}",method = RequestMethod.DELETE)
    @ResponseBody
    public String delete(@PathVariable("id") int id){
        //mock添加

        System.out.println(id);


        return "success";
    }
    @RequestMapping("/user/{uid}/address/{aid}")
    @ResponseBody
    public String findUser4address(@PathVariable("aid") String aid,@PathVariable("uid") int uid){
        System.out.println("收货地址id:"+aid);
        System.out.println("用户id:"+uid);
        return "success";
    }
}

前端

<body>
    <h3>更新操作</h3>
    <form method="post" action="/user/2">
        名字:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        年龄:<input type="text" name="age">
        <input type="submit" value="点我提交表单">
    </form>
    <h3>put操作</h3>
    <form method="post" action="/user">
        <input type="hidden" name="_method" value="put">
        名字:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        年龄:<input type="text" name="age">
        <input type="submit" value="点我提交表单">
    </form>
    <h3>put操作</h3>
    <form method="post" action="/user/1">
        <input type="hidden" name="_method" value="delete">
        <input type="submit" value="点我提交表单">
    </form>
</body>

最后总结

restful风格的url设计
    传统的url设计

        以用户操作为例
        1.根据id查询
            /user/findById?id=xxx
        2.保存用户
            /user/save
            post请求发送 放在表单中
            username=xx&password=xxx&age=18..
        3.更新用户
           /user/update
           id=1&username=xxx&password=xxx
        4.查询所有
            /user/findAll
        5.删除用户
            /user/delete?id=xxx

    restful风格:
        以用户操作为例
        1.根据id查询
            路径      请求方式
            /user/1   GET

        2.保存用户
            路径      请求方式
            /user     PUT
            请求体数据
            username=xx&password=xxx&age=18..
        3.更新用户
            路径      请求方式
           /user/1      POST
           数据还是这个
           username=xxx&password=xxx
        4.查询所有
            路径       请求方式
            /user      GET
        5.删除用户
            路径       请求方式
            user/1     DELETE

    总结:
        restful 传统方式比较起来就是 他把之前设计  动作在路径写着现在呢
        把动作交给了 请求方式来做
        get 获取
        put 增加(更新)
        post 更新(保存)
        delete 删除

        分页查询
        /user/_page  post

        pageNumber=1

        某个人某个收货地址

        /user/2/shouhuo/asda3sdasgdj

第3章 控制器方法的返回值[掌握]

3.1 返回值分类

    /**
     * 某某个需求 不需要model
     *
     *
     * 返回 视图  其实可以直接返回视图的地址字符串  没有必要非得  整个modelandview
     * @return
     */
    @RequestMapping("/test2")
    public String test2(){

        return "product/test";
    }

    /**
     * 我们又想要返回 字符串  又需要数据
     * 只用model
     *
     */
    @RequestMapping("/test3")
    public String test3(Model model){
        String s = new Date().toString();
        model.addAttribute("content",s);

        return "product/test";
    }

3.2 转发和重定向

3.2.1 forward 转发

在这里插入图片描述

3.2.1 Redirect 重定向

    /**
     * 重定向操作方式一
     * @return
     */
    @RequestMapping("/test4")
    public String test4(){


        return "redirect:http://www.baidu.com";
    }

    /**
     * 重定向操作方式二
     * @return
     */
    @RequestMapping("/test5")
    public void test5(HttpServletResponse response) throws IOException {

        response.sendRedirect("http://www.baidu.com");
    }

第4章 交互 json 数据[应用]

4.1 返回值是对象json对象转换

在这里插入图片描述
在这里插入图片描述

导入maven坐标

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

dispatcher-servlet.xml

    <!--
        指明requestMapping 现在版本  为了注入转换器 
        注入json 转化
    -->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <!--
                配置springmvc 相应内容的时候  麻烦你进行一下 jackson转换
            -->
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
        </mvc:message-converters>

    </mvc:annotation-driven>

传统方式

    /**
     * 返回任意对象 返回json格式给前端 传统的方式
     * @return
     */
    @RequestMapping("/test6")
    public void test6(HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=utf-8");
        //手写怎么玩
        Product product = new Product();
        product.setId(1);
        product.setPname("小米手机");
        product.setPrice(2999.99);

        ObjectMapper objectMapper = new ObjectMapper();
        String s = objectMapper.writeValueAsString(product);
        response.getWriter().println(s);
    }

ReponseBody方式
能转json格式就会转json返回,转不了string格式返回

 @RequestMapping("/test7")
    @ResponseBody
    public Product test7(HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=utf-8");
        //手写怎么玩
        Product product = new Product();
        product.setId(1);
        product.setPname("小米手机");
        product.setPrice(2999.99);

        return product;
    }
    @RequestMapping("/test8")
    @ResponseBody
    public String test8(HttpServletResponse response) throws IOException {


        return "xixihaha";
    }

4.2 前端发送json格式数据后端封装采用

@RequestBody使用
在这里插入图片描述

contentType:"application/json;charset=utf-8"设置类型json格式
前端页面

    <script src="../js/jquery.min.js"></script>
    <script>
        function req(){
            //var s={"id":1,"pname":"锤子手机","price":2000};
            //发请求
            $.ajax({
                url:"/product/test9",
                type:"post",
                data:"{\"id\":1,\"pname\":\"锤子手机\",\"price\":2000}",
                contentType:"application/json;charset=utf-8",
                success:function(data){
                    alert(data);
                }
            })
        }
    </script>
</head>
<body>
    我是一个静态页面
    <input type="button" value="点我发送ajax请求参数json格式的字符串" onclick="req()">
</body>

后端

    /**
     *
     *  前端传数据  传json格式的数据
     *
     *  后端需要封装对象的时候  请你 使用 @requestBody springmvc 自动按照json格式给你转换对象
     *  如果不使用@requestBody,默认request.getParamter方式获取,获取json获取不到,
     *  以json格式封装到Product对象里
     * @return
     * @throws IOException
     */
    @RequestMapping("/test9")
    @ResponseBody
    public String test9(@RequestBody Product product, Model model) throws IOException {

        System.out.println(product);
        String s = new Date().toString();
        model.addAttribute("content",s);
        return "success";
    }

第5章 SpringMVC 实现文件上传[应用]

5.1 文件上传的回顾

5.1.1 文件上传的必要前提

A form 表单的 enctype 取值必须是: multipart/form-data
(默认值是:application/x-www-form-urlencoded)
		enctype:是表单请求正文的类型
		B method 属性取值必须是 Post
		C 提供一个文件选择域<input type=”file” />

5.1.2 文件上传的原理分析

在这里插入图片描述

5.1.3 借助第三方组件实现文件上传

在这里插入图片描述

5.2 springmvc 传统方式的文件上传

5.2.1 说明

传统方式的文件上传, 指的是我们上传的文件和访问的应用存在于同一台服务器上。
并且上传完成之后,浏览器可能跳转

5.2.2 实现步骤

5.2.2.1 第一步: 创建 maven 工程并导入 commons-fileupload 坐标

在这里插入图片描述

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
5.2.2.2 第二步:编写 jsp 页面

在这里插入图片描述

5.2.2.3 第三步:编写控制器

在这里插入图片描述
在这里插入图片描述
自己写的控制器

@Controller
public class UploadController {
    /*
    * MultipartFile 就是springmvc 给我们封装好文件对象  参数名字 必须input输入框的 name属性一致
    * */
    @RequestMapping("/upload")
    @ResponseBody
    public String upload(MultipartFile avatar) throws IOException {
        //以前写 你会在这里使用 apache提供文件上传解析包 自己一点点解释出来

        String contentType = avatar.getContentType();
        System.out.println("文件类型:"+contentType);
        String name = avatar.getName();
        System.out.println("代表是你参数 name属性值:"+name);

        String originalFilename = avatar.getOriginalFilename();
        System.out.println("原本的文件名:"+originalFilename);

        InputStream inputStream = avatar.getInputStream();
        FileOutputStream outputStream = new FileOutputStream("/Users/huyoufu/" + originalFilename);

        IOUtils.copy(inputStream,outputStream);

        outputStream.close();
        inputStream.close();

        return "success";
    }
}
5.2.2.4 第四步:配置文件解析器

在这里插入图片描述

5.3 springmvc 跨服务器方式的文件上传

5.3.1 分服务器的目的

在这里插入图片描述

5.3.2 准备两个 tomcat 服务器,并创建一个用于存放图片的 web 工程

在这里插入图片描述
在这里插入图片描述

5.3.3 导入 jersey 的坐标

	<dependency>
		<groupId>com.sun.jersey</groupId>
		<artifactId>jersey-core</artifactId>
		<version>1.18.1</version>
	</dependency>
	<dependency>
		<groupId>com.sun.jersey</groupId>
		<artifactId>jersey-client</artifactId>
		<version>1.18.1</version>
	</dependency>

5.3.4 编写控制器实现上传图片

在这里插入图片描述

5.3.5 编写 jsp 页面

在这里插入图片描述

5.3.6 配置解析器

在这里插入图片描述

第6章 SpringMVC 中的异常处理[理解]

6.1异常处理的思路

  系统中异常包括两类:预期异常和运行时异常 RuntimeException,前者通过捕获异常从而获取异常信息,
后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
  系统的 dao、 service、 controller 出现都通过 throws Exception 向上抛出,最后由 springmvc 前端
控制器交由异常处理器进行异常处理,如下图:

在这里插入图片描述

6.2实现步骤

6.2.1 编写异常类和错误页面

在这里插入图片描述
在这里插入图片描述

6.2.2 自定义异常处理器

在这里插入图片描述

6.2.3 配置异常处理器

在这里插入图片描述

6.2.4 运行结果:

在这里插入图片描述
自己的实例
MyExceptionResolver.java

public class MyExceptionResolver implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ModelAndView modelAndView = new ModelAndView();


        if (ex instanceof MyException1){
            MyException1 exception1= (MyException1) ex;
            modelAndView.addObject("code",exception1.getCode());
            modelAndView.addObject("msg",exception1.getDesc());


        }else if(ex instanceof MyException2){
            MyException2 exception2= (MyException2) ex;
            modelAndView.addObject("code",exception2.getCode());
            modelAndView.addObject("msg",exception2.getDesc());
        }else{
            modelAndView.addObject("code","10001");
            modelAndView.addObject("msg","系统异常");

        }

        modelAndView.setViewName("error/beautiful");


        return modelAndView;
    }
}

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值