SpringMVC学习笔记:springmvc-03

5 数据处理及跳转

5.1 结果跳转方式

5.1.1 ModelAndView

这是ModelAndView对象,根据view的名称,和视图解析器调到指定的页面

页面:{视图解析器前缀} + viewName + {视图解析器后缀}

<!--视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
      id="internalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>
<!--Handler-->
<bean name="/t1" class="com.serene.controller.ControllerTest1"/>

对应Controller类:

public class ControllerTest1 implements Controller {
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //返回一个视图模型对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg", "这是实现Controller接口控制器!");
        mv.setViewName("test");
        return mv;
    }
}

访问路劲

在这里插入图片描述

5.1.2 ServletAPI

通过设置ServletAPI,不需要视图解析器,这里需要注释掉5.1.1中配置文件的代码

1.通过HttpServletResponse进行输出,请求页面打印信息

2.通过HttpServletResponse进行重定向,地址和页面都跳转

3.通过HttpServletResponse进行转发,页面跳转,地址不变

@Controller
public class ResultGoController {
    //1.通过HttpServletResponse进行输出
    @RequestMapping("/resultgo/t1")
    public void test1(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.getWriter().println("Hello,Spring By servlet API");
    }
    //2.通过HttpServletResponse实现重定向 页面、地址都跳转
    @RequestMapping("/resultgo/t2")
    public void test2(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.sendRedirect("/index.jsp");
    }
    //3.通过HttpServletResponse 实现转发 页面跳转,地址不变
    @RequestMapping("/resultgo/t3")
    public void test3(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        //转发
        req.setAttribute("msg", "通过HttpServletResponse 实现转发");
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);
    }
}

5.1.3 SpringMVC

1.通过SpringMVC来实现转发和重定向-无需视图解析器;

测试前,需要将视图解析器注释掉

@Controller
public class ResultSpringMVC {
    @RequestMapping("rsm/t1")
    public String test1(){
        //转发一 页面跳转,地址不变
        return "/index.jsp";
    }
    @RequestMapping("rsm/t2")
    public String test2(){
        //转发二
        return "forward:/index.jsp";
    }
    @RequestMapping("rsm/t3")
    public String test3(){
        //重定向 页面、地址都跳转
        return "redirect:/index.jsp";
    }
}

2.通过SpringMVC来实现转发和重定向-有视图解析器;
重定向中,不需要视图解析器,本质就是重新请求一个新地址

@Controller
public class ResultSpringMVC2 {
    @RequestMapping("rsm2/t1")
    public String test1(){
        //转发一
        return "test";
    }
    @RequestMapping("rsm2/t2")
    public String test2(){
        //重定向
        return "redirect:/index.jsp";
    }
}

5.2 数据处理

5.2.1 处理提交的数据

  1. 提交的域名称和处理方法的参数名一致

    提交数据:http://localhost:8080/user/t1?name=serene

    处理方法:

    @Controller
    @RequestMapping("/user")
    public class UserController {
        //1.提交的域名和处理方法的参数名一致
        @RequestMapping("/t1")
        public String test1(String name, Model model){
            System.out.println("parameter:"+name);
            model.addAttribute("msg","parameter:"+name);
            return "test";
        }
    }
    

    结果:

    在这里插入图片描述

  2. 提交的域名称与处理方法的参数名不一致
    提交数据:http://localhost:8080/user/t2?username=serene

    处理方法:@RequestParam(“username”)

    @Controller
    @RequestMapping("/user")
    public class UserController {
        //2.提交的域名称处理方法和参数民不一致
        @RequestMapping("/t2")
        public String test2(@RequestParam("username") String name, Model model){
            System.out.println("parameter:"+name);
            model.addAttribute("msg","parameter:"+name);
            return "test";
        }
    }
    

    测试结果:
    在这里插入图片描述

  3. 提交的是一个对象

  4. 提交的表单域和对象的属性名一致,参数使用对象即可

    对象对应实体类属性:

    package com.serene.pojo;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    //注解完成javaBean属性,注意导入Lombok依赖
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private int id;
        private String name;
        private int age;
    }
    

    提交方法:http://localhost:8080/user/t3?name=serene

    处理方法:

    @Controller
    @RequestMapping("/user")
    public class UserController {
        //3.前端提交的是一个对象
        @RequestMapping("/t3")
        public String test3(User user, Model model){
            System.out.println("parameter:"+user);
            model.addAttribute("msg", "parameter:"+user);
            return "test";
        }
    }
    

    测试结果:

在这里插入图片描述

说明:如果使用对象的话,前端传递的参数名和对象名必须一致,否则为null。不用传入对象的所有属性。

5.2.2 数据显示到前端

  1. 通过ModelAndView

    未使用注解一直使用的方式,

    public class ControllerTest1 implements Controller {
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            //返回一个视图模型对象
            ModelAndView mv = new ModelAndView();
            mv.addObject("msg", "这是实现Controller接口控制器!");
            mv.setViewName("test");
            return mv;
        }
    }
    
    <!--视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          id="internalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <bean name="/t1" class="com.serene.controller.ControllerTest1"/>
    
    

    2.通过ModelMap

    @Controller
    @RequestMapping("/user")
    public class UserController {
        //ModelMap
        @RequestMapping("/t4")
        public String test4(User user, ModelMap model){
            System.out.println("parameter:"+user);
            model.addAttribute("msg", "parameter:"+user);
            return "test";
        }
    }
    

| 在这里插入图片描述

  1. 通过Model

    5.2.1中的Model方式,此处不举例了

  2. 几种数据显示到前端方式的对比

Model 只有寥寥几个方法适用于储存数据,简化了新手对于 Model 对象的操作个理解;

ModelMap 继承了 LinkedMap,除了实现自身的一些方法,同样继承该类的方法和特性;

ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进性控制展示层的跳转。

当然更多的以后开发考虑的更多的性能和优化,就不能单单仅限于此的了解。

6 乱码问题

测试步骤:

  1. 在首页编写一个提交表单,提交表单方式为 post

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>$Title$</title>
        </head>
        <body>
            $***乱码问题测试!***$
            <form action="/e/t" method="post">
                <input type="text" name="name">
                <input type="submit">
            </form>
        </body>
    </html>
    
    
  2. 编写对应的处理方法

    @Controller
    public class EncodingController {
        @RequestMapping("e/t")
        public String test(String name, Model model){
            System.out.println("name="+name);
            model.addAttribute("msg", "name="+name);
            return "test";
        }
    }
    
    
  3. 首页表单中输入中文测试,发现乱码

在这里插入图片描述

乱码问题在开发中很常见,是一个让程序猿头疼的问题!

以前乱码问题通过过滤器解决,而SpringMVC给我们提供了一个过滤器,可以再web.xml中配置,,修改了xml配置,需要重启服务器!

<!--过滤器解决乱码问题-->
<filter>
    <filter-name>encoding</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>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

此时测试首页表单中传入中文,便不会出现乱码

在这里插入图片描述

如果该过滤器解决不了的乱码问题:

1.修改Tomcat配置文件:设置编码! 路径:/Tomcat/conf/server.xml

<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
          connectionTimeout="20000"
          redirectPort="8443" />

2.自定义过滤器

package com.serene.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;

public class GenericEncodingFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //处理response的字符编码
        HttpServletResponse myResponse=(HttpServletResponse) response;
        myResponse.setContentType("text/html;charset=UTF-8");

        // 转型为与协议相关对象
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        // 对request包装增强
        HttpServletRequest myrequest = new MyRequest(httpServletRequest);
        chain.doFilter(myrequest, response);
    }
    public void init(FilterConfig filterConfig) throws ServletException {
    }

}

//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {

    private HttpServletRequest request;
    //是否编码的标记
    private boolean hasEncode;
    //定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
    public MyRequest(HttpServletRequest request) {
        super(request);// super必须写
        this.request = request;
    }

    // 对需要增强方法 进行覆盖
    @Override
    public Map getParameterMap() {
        // 先获得请求方式
        String method = request.getMethod();
        if (method.equalsIgnoreCase("post")) {
            // post请求
            try {
                // 处理post乱码
                request.setCharacterEncoding("utf-8");
                return request.getParameterMap();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } else if (method.equalsIgnoreCase("get")) {
            // get请求
            Map<String, String[]> parameterMap = request.getParameterMap();
            if (!hasEncode) { // 确保get手动编码逻辑只运行一次
                for (String parameterName : parameterMap.keySet()) {
                    String[] values = parameterMap.get(parameterName);
                    if (values != null) {
                        for (int i = 0; i < values.length; i++) {
                            try {
                                // 处理get乱码
                                values[i] = new String(values[i]
                                                       .getBytes("ISO-8859-1"), "utf-8");
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
                hasEncode = true;
            }
            return parameterMap;
        }
        return super.getParameterMap();
    }

    //取一个值
    @Override
    public String getParameter(String name) {
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        if (values == null) {
            return null;
        }
        return values[0]; // 取回参数的第一个值
    }

    //取所有值
    @Override
    public String[] getParameterValues(String name) {
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        return values;
    }
}

<!--web.xml配置自定义过滤器 注意/* -->
<!--自定义过滤器解决乱码问题-->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>com.serene.filter.GenericEncodingFilter</filter-class>
        <!--<init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>-->
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

这是大神写的一个过滤器,一般情况下,SpringMVC默认的编码处理就已经能够很好解决乱码问题了!

乱码问题,需要平时多注意,在尽可能设置编码的地方都同意设置为 utf-8

对应代码:springmvc-04-controller

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值