SpringMVC笔记(四)

234 阅读3分钟

1. 结果跳转方式

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>

对应的Controller控制器

public class ControllerTest1 implements Controller {
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        //返回一个模型视图对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","ControllerTest1");
        mv.setViewName("test");
        return mv;
    }
}

1.2 ServletAPI

通过设置ServletAPI,不需要视图解析器

  1. 通过HttpServletResponse进行输出

  2. 通过HttpServletResponse进行重定向

  3. 通过HttpServletResponse实现转发

    @Controller
    public class ResultGo {
     
        @RequestMapping("/result/t1")
        public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
            rsp.getWriter().println("Hello");
        }
     
        @RequestMapping("/result/t2")
        public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
            rsp.sendRedirect("/index.jsp");
        }
     
        @RequestMapping("/result/t3")
        public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
            //转发
            req.setAttribute("msg","/result/t3");
            req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp);
        }
     
    }
    

1.3 SpringMVC

通过SpringMVC来实现转发和重定向,视图解析器可以使用也可以不使用

@Controller
public class ResultSpringMVC2 {
    @RequestMapping("/rsm2/t1")
    public String test1(){
        //转发
        return "test";
    }

    @RequestMapping("/rsm2/t2")
    public String test2(){
        //重定向
        return "redirect:/index.jsp";
        //hello.do为另一个请求/
        //return "redirect:hello.do";
    }
}

2. 数据处理

2.1 处理提交数据

  1. 提交时候的参数名和处理方法的参数名一致,则会自动匹配

    @RequestMapping("/hello")
    public String hello(String name){
        System.out.println(name);
        return "hello";
    }
    
  2. 提交时候的参数名和处理方法的参数名不一致,需要在方法的参数列表中使用@RequestParam注解进行手动绑定

    //@RequestParam("username") : username 提交的域的名称 .
    @RequestMapping("/hello")
    public String hello(@RequestParam("username") String name){
        System.out.println(name);
        return "hello";
    }
    
  3. 提交的是一个对象

    • 如果提交的是一个对象,则参数直接使用对象即可
    @RequestMapping("/user")
    public String user(User user){
        System.out.println(user);
        return "hello";
    }
    

3. 数据显示到前端

3.1 通过ModelAndView

public class ControllerTest1 implements Controller {
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        // 返回一个模型视图对象
        ModelAndView mv = new ModelAndView();
        mv.addObject("msg","ControllerTest1");
        mv.setViewName("test");
        return mv;
    }
}

3.2 通过ModelMap

@RequestMapping("/hello")public String hello(@RequestParam("username") String name, ModelMap model){    //封装要显示到视图中的数据    //相当于req.setAttribute("name",name);    model.addAttribute("name",name);    System.out.println(name);    return "hello";}

3.3 通过Model

@RequestMapping("/ct2/hello")public String hello(@RequestParam("username") String name, Model model){    //封装要显示到视图中的数据    //相当于req.setAttribute("name",name);    model.addAttribute("msg",name);    System.out.println(name);    return "test";}

3.4 三种方式对比

  • Model 只有寥寥几个方法只适合用于储存数据,简化了Model对象的操作和理解
  • ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性
  • ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转

4. 乱码问题

我们可以通过修改配置文件web.xml中的过滤器,spring自带CharacterEncodingFilter过滤器

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

也可以使用自定义的过滤器

package top.linzeliang.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;/** * 解决get和post请求 全部乱码的过滤器 */public class GenericEncodingFilter implements Filter {    @Override    public void destroy() {    }    @Override    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);    }    @Override    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;    }}