学习SpringMVC必知必会(3)~springmvc的请求和

2022-03-27  本文已影响0人  一乐乐

一、处理器方法响应处理

Controller方法该怎么返回、Controller数据该怎么进行共享

1、Controller方法返回void

    //返回void类型,此时可以把Controller方法当做Servlet使用【适合用来下载文件】
    @RequestMapping("/test1")
    public void test(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //请求转发
        request.getRequestDispatcher("/WEB-INF/views/welcome.jsp").forward(request, response);
        //设置共享数据
        request.setAttribute("msg", "hello");
        //输出json格式
        response.setContentType("text/json;charset=utf-8");
        response.getWriter().println(); 
    }

2、【常用】返回ModelAndView

    //返回ModelAndView
    @RequestMapping("/test3")
    public ModelAndView test3() {
        ModelAndView mv = new ModelAndView();
        //设置视图名称
//      mv.setViewName("/WEB-INF/views/welcome.jsp");
        mv.setViewName("welcome");
        mv.addObject("msg", "返回ModelNAndView");//设置共享数据的key和value
        mv.addObject("叩丁狼教育");//设置共享数据的value,此时会把value类型的首字母作为key:string
        return mv;
    }

3、【常用】返回String类型(是逻辑视图名称),参数是Model类型(是共享数据)

    //返回string,逻辑视图名称,此时需要结合参数Model类型 一起使用
    @RequestMapping("/test4")
    public String test4(Model model) {
        //设置共享数据
        model.addAttribute("叩丁狼");
        model.addAttribute("msg", "教育");
        return "welcome";//设置跳转的视图
    }



二、请求跳转

1、请求转发

    //请求转发,浏览器地址栏不变,可以共享请求中的数据
    //原理:request.getRequestDispatcher("").forward(request, response);
    @RequestMapping("/test5")
    public String test5(Model model) {
        return "forward:/hello.jsp";//设置跳转的视图
    }

2、URL重定向

    //重定向,浏览器地址栏改变,不能共享请求中的数据
    //原理:request.sendRedirect("");
    @RequestMapping("/test6")
    public String test6(Model model) {
        return "redirect:/hello.jsp";//设置跳转的视图
    }

■ 请求资源的路径问题:[总结:访问资源的时候,都使用/开头]

✿ 请求转发和URL重定向的选择:

请求转发/URL重定向 请求转发 URL重定向
地址栏改变? 不会 会改变
共享数据? 可以 不可以?
表单重复提交? 会发生 不会发生


3、URL重定向共享数据

    //重定向:从a跳转到b    
    @RequestMapping("/a")
    public String a(RedirectAttributes ra) {
        ra.addAttribute("msg1", "a传递的数据");
        ra.addFlashAttribute("msg2", "msg2");
        return "redirect:/response/b";//设置跳转的视图
    }
    
    @RequestMapping("/b")
    public ModelAndView b(String msg1, @ModelAttribute("msg2") String msg2) {
        System.out.println("msg1:" + msg1);
        System.out.println("msg2:" + msg2);
        return null;
    }
图片.png



三、处理器方法参数处理(接收请求参数的处理

1、request 和 response 参数

■ 情况一:为了操作Servlet API 对象,此时可以直接以参数形式传递,也可以直接使用DI注入。

@Controller
@RequestMapping("/request")
public class HandlerRequestController {

    @Autowired
    private ServletContext context;
    
    @RequestMapping("/test1")
    public void test(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException, IOException {
        System.out.println("request:" + request);
        System.out.println("response:" + response);
        System.out.println("session:" + session);
        System.out.println("ServletContext:" + this.context);
        
    }
}

因为Controller(Servlet) 是单例的,线程不安全,一般不用成员变量,除非要共享的数据,才作为成员变量。


2、简单类型参数

■ 获取请求参数:【保证输入的参数和定义的形参名称一致】

    //获取请求参数:通过保证请求参数名称和Controller方法定义的形参(入参)同名即可
    @RequestMapping("/test2")
    public void test2(String username, int age)  {
        System.out.println(username);
        System.out.println(age);
    }
图片.png

■ 获取请求参数:【输入的参数和定义的形参名称不一致】----注解@RequestParam

    //获取请求参数:若请求参数和请求参数名称和形参不同----注解@RequestParam
    @RequestMapping("/test3")
    public void test3(@RequestParam("name") String username, @RequestParam(value="age",required=false) Integer age)  {
        System.out.println("username:" +username);
        System.out.println("age:" + age);
    }

3、中文乱码处理

■ 在"全局配置"【web.xml】,添加上编码过滤器:

    <!-- (针对post请求)配置过滤器 -->
    <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>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

4、restfull风格传参

    //restfull风格传递参数
    //PathVariable: 可以将url中占位符绑定到方法的形参中
    @RequestMapping("/r/{id}")
    public ModelAndView rest(@PathVariable("id") Integer id) {
        System.out.println("id:" + id);
        return null;
    }

5、数组和List类型参数

    //接收一个参数有很多值的情况
    //使用数组:可以直接接收  Long[] ids
    //使用List: 不可以直接接收,可以在对象中存在一个集合   List<Long> ids
    @RequestMapping("/batchDelete") //batchDelete?ids=10&ids=20&ids=30
    public void batchDelete(FormBean fb) {
        System.out.println(fb.getIds());    
    }
★ 操作一个参数有多个值的情况,一般直接使用数组接收即可,或者使用javaBean对象来封装数据。

6、■ 获取请求参数:

JavaBean类型参数【将请求参数封装成一个对象

    //封装成一个对象
    @RequestMapping("/bean") //batchDelete?ids=10&ids=20&ids=30
    public void bean(User user) {
        System.out.println(user);   
    }
图片.png


✿ 总结处理器方法参数处理:

1、直接把请求参数封装成javaBean对象
2、配置解决中文乱码的过滤器
3、简单类型参数----输入参数名和定义的形参不同-> @ResultParam
4、使用数组接收多个参数
5、restfull风格传参



四、ModelAttribute

    //ModelAttribute注解:
    /*
     *1、给共享的model数据设置key名,贴在形参上,也可以贴在方法上
     *  针对复合类型(非简单类型)参数,缺省情况下就会放到model中(共享), 缺省的key就是类型首字母小写
     * 2、可以标注一个非请求处理的方法,被标注的方法,每次在请求处理方法之前都会优先被执行[存放多个请求需要共享的数据]
     */
    @RequestMapping("/test11")
    public String test1(@ModelAttribute("u") User user)  {
        System.out.println(user);
        return "welcome";
    }



五、其他请求信息

1、获取请求头 @RequestHeader

    @RequestMapping("/test1")
    public ModelAndView test1(@RequestHeader("User-Agent") String userAgent) {
        System.out.println("test1");
        System.out.println("User-Agent:" + userAgent);
        return null;
    }

2、获取Cookie @CookieValue

    @RequestMapping("/test1")
    public ModelAndView test1(@RequestHeader("User-Agent") String userAgent, @CookieValue("Webstorm-5895a979") String cName) {
        System.out.println("test1");
        System.out.println("User-Agent:" + userAgent);
        System.out.println("cName:" + cName);
        return null;
    }

3、操作HttpSession @SessionAttributes

@Controller
@RequestMapping("/other")
@SessionAttributes("errMsg")
public class OtherController {

    @RequestMapping("/test2")
    public String test2(Model model) {
        System.out.println("操作session");
        model.addAttribute("errMsg", "错误信息");
        return "redirect:/hello.jsp";
    }
}



六、数据绑定流程

图片.png

1、框架把 ServletRequest 对象和请求参数传递给 DataBinder

2、DataBinder 首先调用 Spring Web 环境中的 ConversionService 组件,进行数据类型转换和格式化等操作,将 ServletRequest 中的信息填充到形参对象中;

3、DataBinder 然后调用 Validator 组件对已经绑定了请求消息数据的形参对象进行数据合法性校验

4、DataBinder 最后输出数据绑定结果对象 BindingResult



七、多对象封装传参

    /*
     * 需要吧表单数据封装到多个对象中去,若各个对象有相同的属性时
     * 不知道该把哪一个参数封装到哪一个对象
     */
    @RequestMapping("/save")
    public ModelAndView save(Cat cat, Dog dog) {
        System.out.println("提交数据");
        System.out.println(cat);
        System.out.println(dog);
        return null;
    }
    <form action="/save" method="post">
        猫名:<input type="text" name="name" /><br/>
        猫年龄:<input type="text" name="age" /><br/>
        狗名:<input type="text" name="name" /><br/>
        狗年龄:<input type="text" name="age" /><br/>
        <input type="submit" value="提交">
    </form>
图片.png

解决:

    <form action="/save" method="post">
        猫名:<input type="text" name="cat.name" /><br/>
        猫年龄:<input type="text" name="cat.age" /><br/>
        狗名:<input type="text" name="dog.name" /><br/>
        狗年龄:<input type="text" name="dog.age" /><br/>
        <input type="submit" value="提交">
    </form>
    //从参数--> 对象,封装规则需要我们来设置
    
    //自定义数据绑定注册,将请求参数转化成对应对象的属性
    @InitBinder("cat")
    public void initBinderCat(WebDataBinder binder) {
        //设置字段以什么做为前缀
        binder.setFieldDefaultPrefix("cat.");
    }
    
    @InitBinder("dog")
    public void initBinderDog(WebDataBinder binder) {
        //设置字段以什么做为前缀
        binder.setFieldDefaultPrefix("dog.");
    }
图片.png



八、JSON数据处理

1、依赖:

2、处理json的注解 @ResponseBody @RestController @RequestBody

(1) @ResponseBody: <font color=orange>处理响应</font>,把对象转化成json字符串

    //把单个对象/Map转化成json格式
    @RequestMapping("/test1")
    @ResponseBody
    public User test1() {
        User u = new User();
        u.setUsername("shan");
        u.setAge(18);
        return u;
    }
    
    //把多个对象转化成json格式
    @RequestMapping("/test2")
    @ResponseBody
    public List<User> test2() {
        User u = new User();
        u.setUsername("shan");
        u.setAge(18);
        return Arrays.asList(u, u, u);
    }


    //返回一个String,默认返回字符串是逻辑视图名称,加上@ResponseBody,当做json格式的数据
    @RequestMapping(value="/test3", produces="application/json;charset=utf-8")
    @ResponseBody
    public String test3() {
        return "success, 你好~";
    }

(2) @RestController = @Controller + @ResponseBody

(3) @RequestBody



九、日期类型处理

1、前台往后台传参转化为Date类型

★ 时间格式的注解:@DateTimeFormat

    //从前台---->后台传递参数 java.lang.String -> java.util.Date
    //请求参数是Date类型
    @RequestMapping("/test1")
    public ModelAndView test(@DateTimeFormat(pattern = "yyyy-MM-dd")Date date) {
        System.out.println("date:" + date);
        if(date instanceof Date) {
            System.out.println("yes");
        }
        return null;
    }
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        //日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        //属性编辑器
        binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(sdf, true));
    }
@ControllerAdvice
public class DateFormateAdvice {

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        //日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        //属性编辑器
        binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(sdf, true));
    }
}


2、jsp中显示时间格式:将欧美时间格式-->中国时间格式

(1)导入jar包[tomcat服务器examples案例下的lib就有]:

(2)配置引入标签库taglib

<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> 

(3) 使用jstl:

    <% pageContext.setAttribute("myDate", new java.util.Date()); %> 
    北京时间: <fmt:formatDate value="${myDate}" pattern="yyyy=MM-dd HH:mm:ss"/>
图片.png


3、后台往前台响应JSON时---Date类型

(1)方法1:在springmvc框架配置中添加json类型转化相关的配置[配置全局解析器]:

    <!-- MVC注解解析器 -->
    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                        <property name="dateFormat">
                            <bean class="java.text.SimpleDateFormat">
                                <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" />
                            </bean>
                        </property>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

(2)方式2:使用注解@JsonFormat

@Data
public class User {
    private Long id;
    private String username;
    private Integer age;
    //@DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date hireDate;  
}

★ 注意:@DateTimeFormat前台往后台传参【前台String类型-》后台Date类型】

★ 注意: 是后台响应给前台,响应为json格式(对时间Date类型的处理)


如果本文对你有帮助的话记得给一乐点个赞哦,感谢!

上一篇下一篇

猜你喜欢

热点阅读