SpringMVC(day02)SessionAttribute注解、restful风格、静态资源放行

本文深入探讨SpringMVC框架的关键特性,包括@ModelAttribute和@SessionAttribute注解的使用、RestFul风格、控制器方法的返回值、JSON数据交互、文件上传及异常处理等,为开发者提供全面的技术指导。

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

一、教学目标

1、ModelAttribute和SessionAttribute注解的使用

2、RestFul风格

3、控制器方法的返回值

4、交互JSON数据

5、springMVC实现文件上传

6、springMVC异常处理

二、ModelAttribute和SessionAttribute注解的使用

a. @ModelAttribute标记在方法上
    特点:当执行控制器中任何一个方法时,都会先执行@ModelAttribute标记的方法
    缺点:慎重使用,因为执行控制器中任何一个方法时,都会先执行@ModelAttribute标记的方法, 效率太低
    UserUpdateController
    UserQueryController
b. 用法一:


     @ModelAttribute
    public User findById(Integer id){
        User user = new User();
        user.setUsername("王五");
        user.setSex("女");
        return user;
    }

    /**
     * update user set username = ? ,sex = ? where id = ?
     * @ModelAttribute:在执行控制器中任何一个方法时,都会先执行
     *      findById方法返回一个User对象
     *      判断参数user中的属性是否为null,如果为null,则使用findById的方法返回值中的数据覆盖
     * @param user
     * @return
     */
    @RequestMapping(value = "/testUpdate",method = RequestMethod.POST)
    public String testUpdate(User user){
        System.out.println(user);
        System.out.println("更新");
        return "show";
    }


c.方法二:


 @ModelAttribute
    public void findById(Integer id, Map<String ,Object> map){
        User user = new User();
        user.setUsername("王五");
        user.setSex("女");

        map.put("aa",user);
    }

    @RequestMapping(value = "/testUpdate",method = RequestMethod.POST)
    public String testUpdate(@ModelAttribute("aa") User user){
        System.out.println(user);
        System.out.println("更新");
        return "show";
    }

=================================================================================

d. 注解@SessionAttributes:在session范围内存储对象


    1) @SessionAttributes({"username","password"}) 在类上标记该注解
        在session范围可以存储这两个变量名

    2) /**
     * 把用户名和密码存入到Session范围内
     */
    @RequestMapping("/testPut")
    public void testPut(Model model){
        model.addAttribute("username","zhangsan");
        model.addAttribute("password","123456");
    }

   3)  /**
     * 获取session范围内的对象
     */
    @RequestMapping("/testGet")
    public void testGet(ModelMap modelMap){
        Object username = modelMap.get("username");
        System.out.println(username);
        Object password = modelMap.get("password");
        System.out.println(password);
    }

    4) /**
     * 清空session
     * @param sessionStatus
     */
    @RequestMapping("/testClear")
    public void testClear(SessionStatus sessionStatus){ 
            sessionStatus.setComplete();
    }

三、RestFul风格

a. rest  是一种编程风格
b. 满足了rest风格的网站就是restful风格
c. 只是一种规范,不是规则
d. 根据id获取一个用户: /user/findById?id=1                  restful风格:/user/operate/1   使用get方式提交
    根据id删除一个用户:/user/delById?id=1                    restful风格:/user/operate/1   使用delete方式提交
    更新一个用户:/user/update?id=1&username=zzz     restful风格:/user/operate/1   使用put方式提交
    添加一个用户:/user/save?id=1&username=zzz        restful风格:/user/operate      使用post方式提交
e. 根据id获取(GET,url)
    页面
        http://localhost:8080/user/operate/1
    方法
        /**
     * 根据id查询
     * @param id
     * @return
     */
    @RequestMapping(value = "/operate/{id}",method = RequestMethod.GET)
    public String findById(@PathVariable("id") Integer id){
        System.out.println("findById:"+id);
        return "show";
    }

f. 添加一个用户(POST,表单)
    页面
     <%--请求保存用户--%>
    <form action="${pageContext.request.contextPath}/user/operate/1" method="post">
        <input type="submit" value="提交">
    </form>
    方法
        /**
     * 保存用户
     * @param id
     * @return
     */
    @RequestMapping(value = "/operate/{id}" , method = RequestMethod.POST)
    public String save(@PathVariable("id") Integer id){
        System.out.println("save:" + id);
        return "show";
    }


 

在web.xml中开启另外两种提交方式(put,delete)

  <!--开启另外两种提交方式:put, delete-->
  <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>

h. 更新用户
     页面:
     <%--请求更新用户--%>
    <form action="${pageContext.request.contextPath}/user/operate/1" method="post">
        <%--要使用put,delete提交方式
                 1) 在web.xml开启put和delete提交方式
                 2) 表单的提交方式必须post
                 3) 表单中必须设置一个隐藏域 name=_method value=PUT
                 4) 请求的方法返回值必须以流的形式返回,在方法上标记注解:@ResponseBody
                       流的形式返回: response.getWriter().print()
                --%>

        <input type="hidden" name="_method" value="PUT">
        <input type="submit" value="更新">
    </form>
    方法
     /**
     * 更新用户
     * @param id
     * @return
     */
    @RequestMapping(value = "/operate/{id}" , method = RequestMethod.PUT)
    @ResponseBody
    public String update(@PathVariable("id") Integer id){
        System.out.println("update:" + id);
        return "show";
    }
 i. 删除用户
     页面
     <%--请求删除用户--%>
    <form action="${pageContext.request.contextPath}/user/operate/1" method="post">
        <input type="hidden" name="_method" value="DELETE">
        <input type="submit" value="删除">
    </form>
    方法
     /**
     * 删除用户
     * @param id
     * @return
     */
    @RequestMapping(value = "/operate/{id}" , method = RequestMethod.DELETE)
    @ResponseBody
    public String delById(@PathVariable("id") Integer id){
        System.out.println("delById:" + id);
        return "show";
    }

四、控制器方法的返回值

1、返回值为void类型

a. 方法一:

   @RequestMapping("/testVoid")
   public void testVoid(){
        System.out.println("测试没有返回值");
        //因为没有指定返回值页面,会自动截取请求路径,进入视图解析器,拼接完整的路径
        //可以对应的路径下创建对应的jsp页面
   }

b. 方法二:response重定向

    @RequestMapping("/testVoid2")
    public void testVoid2(HttpServletResponse response){
        System.out.println("测试没有返回值");
        try {
            //重定向不能进入web-inf路径
            //转发可以进入web-inf路径
            response.sendRedirect("/index.jsp");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

//重定向不能进入web-inf路径

c. 方法二:servlet转发

//转发可以进入web-inf路径

    @RequestMapping("/testVoid3")
    public void testVoid3(HttpServletResponse response, HttpServletRequest request){
        System.out.println("测试没有返回值");
        try {
            request.getRequestDispatcher("/WEB-INF/show.jsp").forward(request,response);
        } catch (ServletException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2、返回值为String类型(常用)

a. 默认的情况:转发请求,返回值直接进入视图解析器,拼接前缀和后缀,完整的路径

    /**
     * 方法的返回值为String类型
     *      返回值直接进入视图解析器,拼接前缀和后缀,完整的路径
     * @return
     */
    @RequestMapping("/testReturnString")
    public String testReturnString(){
        return "show";
    }

 

b. 请求重定向

     /**
     * 执行保存操作-- 重新查询 : save -- redirect:findAll
     *
     *      redirect:重定向, 不能进入web-inf
     *   redirect:添加了redirect后则不会进入视图解析器,需要配置完整的路径
     * @return
     */

    @RequestMapping("/testReturnString2")
    public String testReturnString2(){
        return "redirect:/index.jsp";
    }

 

不进入视图解析器

 c. 请求转发

    /**
     * forward: 转发,不会进入视图解析器,需要配置完整的路径
     * @return
     */
    @RequestMapping("/testReturnString3")
    public String testReturnString3(){
        return "forward:/WEB-INF/show.jsp";
    }

3、返回值为ModelAndView类型(常用)

a. ModelAndView:   Model 模型:封装数据  view 视图: 指定页面  ---> 模型和视图

b.

/**
     * 返回值类型为ModelAndView,包含数据和视图页面
     * @return
     */
    @RequestMapping("/testReturnModelAndView")
    public ModelAndView testReturnModelAndView(){
        //准备数据--数据库查询
        List<User> userList = new ArrayList<>();
        User user = new User();
        user.setUsername("zhangsan");
        user.setSex("男");
        user.setId(2);

        User user1 = new User();
        user1.setUsername("zhangsan1");
        user1.setSex("女");
        user1.setId(1);

        userList.add(user);
        userList.add(user1);
        ModelAndView modelAndView = new ModelAndView();
        //添加数据
        modelAndView.addObject("userList",userList);
        //指定页面
        modelAndView.setViewName("show");
        return  modelAndView;
    }

五、交互JSON数据

引入静态资源后,必须静态资源放行

1. 引入json依赖

    <!--引入json的依赖-->
    <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>

 b. ReqeustBody注解

    /**
     * @RequestBody: 可以把所有参数转换为字符串
     * @param body
     */
    @RequestMapping("/testRequestJson2")
    public void testRequestJson2(@RequestBody  String body){
        System.out.println(body);
    }

对比有RequestBody注解与否

c. ResponseBody注解(数据以流的方式返回

 

@RequestBody和@ResponseBody综合

六、SpringMVC实现文件上传

1、文件上传

a、引入依赖

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

 

b、spring-mvc.xml 配置文件

    <!-- 配置文件上传解析器 -->
    <!-- id的值是固定的-->
    <bean id="multipartResolver"
          class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 设置上传文件的最大尺寸为5MB -->
        <property name="maxUploadSize">
            <value>5242880</value>
        </property>
    </bean>

c、页面配置

    <%--
        上传文件的表单前提
            1) 提交方式必须是post
            2) 表单的类型必须:multipart/form-data, 多功能表单数据
            3) 必须有一个type=file的表单元素
    --%>

<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

    <form action="${pageContext.request.contextPath}/user/uploadServer" method="post" enctype="multipart/form-data">
        <input type="text" name="username"> <br>
        <input type="file" name="upload"><br>
        <input type="submit" value="上传">
    </form>
</body>

</html>

d、controller代码

2、跨服上传

a、引入依赖

    <!--引入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>

b、修改tomcat配置

1. tomcat默认不能跨服上传的(修改后可以上传)
2. tomcat/conf/web.xml     
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
    <!--需要添加的-->
        <init-param>
        <param-name>readonly</param-name>
        <param-value>false</param-value>
    </init-param>

 

c、配置图片服务器

1. 创建一个web项目
2. 配置一个tomcat,与原来tomcat端口号不一致
3. 在webapp目录下创建一个upload目录,空的文件夹不会编译,需要在upload目录添加(任意)一个文件

过程:

七、SpringMVC的自定义的异常统一处理

1. 自定义异常类

package com.itheima.exception;

/**
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
public class CustomException extends  Exception {

    private String message;

    public CustomException(String message) {//构造方法
        super(message);   //调用父类具有相同形参的构造方法
        this.message = message;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

2. 定义异常的统一处理对象--实现接口:HandlerExceptionResolver

3. 错误页面

<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${message} //attributeName
</body>
</html>

 

总结

1. @ModelAttribute ,@SessionAttribute
2. restful
3. 控制器方法的返回值
   void : 
   String :
   ModelAndView: 视图和模型
4. json数据的交互
   @RequestBody: 
   @ResponseBody:
5. 文件上传: upload.trsansferTo(new File("path"))
6. 跨服上传文件:
7. 统一处理异常:

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值