Spring Web MVC

Spring Web MVC需要使用IOC功能。

用于开发MVC结构的Web程序。

一.MVC思想

   将程序组件分为模型,视图,控制器三部分。

二.Spring如何实现MVC

     a.浏览器发出一个HTTP请求

     b.请求首先进入DispatcherServlet主控制器

     c.主控制器调用HandlerMapping组件根据请求找映射的Controller处理

     d.执行Controller处理方法,将返回结果给ViewResolver组件

     e.ViewResolver组件根据Controller返回结果定位视图JSP,将模型数据传递给JSP

     f.由JSP生成响应结果,给浏览器输出


spring MVC_第1张图片

发请求到DispatcherServlet,然后到HandlerMapping到Controller1接下来返回一个ViewResolver到视图。


eg:页面上发出hello.do请求,首先经过web.xml,知道.do请求需要进入到DispatcherServlet,DispatcherServlet去applicationContext.xml里面

        寻找handlerMapping组件,根据mapping名为hello.do找hello.do找helloController组件处理。根据helloController里的ModelAndView和applicationContext.xml的prefix和suffix配置去找到/WEB-INF/hello.jsp

eg1:显示登录页面

/tologin.do

—>DispatcherServlet(配置)//充当主控制器,发请求时先给他

—>hanlderMapping(配置)//定义Servlet请求和Controller对应关系,根据applicationContext.xml配置解析对应的哪一个Controller

—>toLoginController(编写+配置)//调用DAO模型组件

—>ViewerResolver(配置)//封装,转发,重定向到JSP视图

—>WEB-INF/login.jsp(编写)


3.Spring Web MVC处理流程

a.RequestMappingHandlerMapping组件

   @RequestMapping(“login.do”)该标记用在Controller业务方法前

b.Controller编写和配置

   取消了实现Controller接口及方法约定,可以允许程序员按需灵活定义业务方法;

public ModelAndView或String 方法名(根据request,session,response)

Controller需要扫描到Spring容器,必须使用@Controller

 eg: public String execute(){

          return “hello”;

          }

d.Controller如何接收请求参数

   1)利用HttpServletRequest

   *2)利用业务方法参数(少量参数时使用)

          *--参数名与请求参数key保持一致

          —利用@RequestParam(“key")

  *3)利用实体对象当方法参数(大量参数时使用)

使用建议:少量参数使用2);大量参数使用3);如果客户端表单数据没有格式检查,遇到非字符串类型参数建议使用1)

e.如何向响应JSP传值

     *1)利用HttpServletRequest

     2)利用ModelAndView做返回值

     *3)利用ModelMap方法参数

     4)使用@ModelAttribute(“key")

          public String checkLogin(@ModuleAttribute(“user”) String username){

               return “ok”;}//ok.jsp使用${user}

          @ModelAttribute(“user")

          public String getName(){

               return “tom”;}

          等价于model.put(“user”, getName());//${user}即tom

f.Controller如何使用Session

代码示例:

web.xml:


    webLogin2
    org.springframework.web.servlet.DispatcherServlet
    
        contextConfigLocation
        classpath:applicationContext.xml
    



    webLogin2
    *.do

handlermapping和controller:

@Controller
public class LoginController {
    //登录按钮处理
    @RequestMapping("/login.do")
    public String checkLogin3(String username, String password, ModelMap modelMap, HttpSession session){
        if ("root".equals(username) && "1234".equals(password)){
            modelMap.put("user", username);
            session.setAttribute("username", username);
            return "ok";//ok.jsp 使用${user}
        } else {
            modelMap.put("msg", "用户名或密码错误");
            return "login";//login.jsp使用${msg}
        }
    }

spring配置:










    
    
    
    
    
    

ok.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>





${user} login success

    session内容: ${sessionScope.username}

login.jsp:

<%@ page language="java" pageEncoding="UTF-8"%>





用户登录

${msg} 用户名:
密码:

访问:http://localhost:8090/webLogin2_war(此处为自己定义的war包名)/login.do

用正确的用户名密码进入显示:

root login success

session内容: root


4.Spring Web MVC

1) 解决中文接收乱码问题



   myfilter
   org.springframework.web.filter.CharacterEncodingFilter
   
       encoding
       UTF-8
   



   myfilter
   *.do
   


2)如何处理异常

    a.全局异常处理:SimpleMappingExceptionResolver

@Controller
public class ExceptionController {

    @RequestMapping("/exception.do")
    public String ex(){
            String s = null;
            s.length();
            return "ok";

    }
}

此时访问exception.do会抛出nullpoint异常,需要进行异常处理,使用内置的全局异常处理方法

applicationContext.xml配置:




此时处理流程图:

    spring MVC_第2张图片

    b.局部异常处理:@ExceptionHandler

public String xxx(HttpServletRequest request, Exception e){}

@Controller
public class AgeController {

    @RequestMapping("/toage.do")
    public String toage(){
        //检查session里是否有username
        return "age";//进入age.jsp
    }

    @RequestMapping("/age.do")
    public String age(String birth, ModelMap modelMap) throws Exception {
        //接收用户输入的生日,计算年龄
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD");
        Date birth1 = sdf.parse(birth);
        int result = now.getYear() - birth1.getYear();
        modelMap.put("msg", "年龄为: " + result);
        return "age";//进入age.jsp,${msg}
        //当出现异常时无法返回String故进入handleException方法
    }

    /*当前Controller异常处理,
    * 当执行该方法后,不会再调用ExceptionResolver
    */
    @ExceptionHandler//局部异常处理方法
    public String handleException(HttpServletRequest request, Exception e) {
        request.setAttribute("msg", "输入信息有误导致计算失败");
        return "age";//返回age.jsp
    }

}

    c.自定义ExceptionResolver(实现HandlerExceptionResolver接口)

先写自己的异常处理类:

public class MyExceptionHandler implements HandlerExceptionResolver {

    public ModelAndView resolveException(HttpServletRequest request,
                                         HttpServletResponse response,
                                         Object method, Exception e) {
        //将异常信息写入文件
        System.out.println("将异常信息写入文件: " + e);
        //跳转到错误页面
        ModelAndView mav = new ModelAndView();
        mav.setViewName("error");
        return mav;
    }
}

eorror.jsp

<%@ page language="java" pageEncoding="UTF-8" %>





系统繁忙

注释掉applicationContext.xml中的全局异常处理,写上自己的异常处理类:



此时访问exception.do当程序出错时页面将显示系统繁忙字样

spring MVC_第3张图片

3)如何实现登录权限检查

    使用session进行约定值判断。

    实现方法:1.采用Filter(通用解决方法);2.采用拦截器(Spring WEB MVC)

    a.拦截器组件简介

      拦截器组件时SpringMVC特有组件。

      拦截器组件可以在Controller之前拦截;可以在Controller之后拦截;可以在JSP解析完毕给浏览器输出之前拦截。

    b.拦截器使用方法

        首先编写一个拦截器组件(实现HandlerInterceptor接口)

        在约定方法中添加要插入的逻辑然后在applicationContext.xml中配置

spring MVC_第4张图片

拦截器类:

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    //controlller之前,权限检查,登录检查
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("---preHandle实现登录检查---");
        HttpSession session = request.getSession();
        //获取登录成功后放置的用户信息
        String name = (String) session.getAttribute("username");
        if (name != null) {//登录过
            return true;//继续执行mvc后续流程
        } else {//登录失效(session失效)或登录失败
            response.sendRedirect("/tologin.do");
            return false;//终止mvc后续流程
        }
    }

    @Override
    //controller之后,统计请求到处理开始到完毕的日志,执行的时间性能监控,检查耗时项
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("---postHandle---");
    }

    @Override
    //请求处理完毕,输出之前。统计请求到处理开始到完毕的日志,执行的时间性能监控,检查耗时项
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("---afterHandle---");
    }
}

applicationContext.xml