Springmvc(三)

复习

springmvc框架:

用户请求url到DispatcherServlet前端控制器,相当于中央调度器,降低系统各组件之间耦合度

DispatcherServlet前端控制器通过HandlerMapping根据url找到Handler。

DispatcherServlet前端控制器通过HandlerAdapter处理器适配器执行Handler。

DispatcherServlet前端控制器拿着Handler返回的ModelAndView通过视图解析器ViewResolver去进行视图解析。

视图解析:将程序中写的逻辑视图名,转成真正的视图(springmvc通过view表示各各不同类型的视图)。
DispatcherServlet前端控制器调用View的渲染方法进行视图渲染(将ModelAndView中的Model放到request域)。

要掌握springmvc的注解开发,企业中常用springmvc注解开发。

使用专门注解处理器映射器(RequestMappingHandlerMapping)和处理器适配器(RequestMappingHandlerAdapter)。
<mvc:annotation-driven/>可以代替上边的处理器映射器和适配器的配置。

在Handler(Controller)中定义很多的方法,一个方法通过RequestMapping和url进行映射。

方法返回值:ModelAndView、string(jsp的逻辑视图名)、void(通过response将数据输出成json)

方法输入参数(形参):springmvc需要将请求的key/value(串,id=001&type=t002)、解析、绑定到Handler(Controller)中方法的形参上。
springmvc默认支持多类型的参数绑定。

默认支持哪些类型:
HttpServletRequest、response、session、Model(用于将数据填充到request域)

@requestParam注解:用于绑定单个请求参数,常用于简单类型参数(Integer、String 、Float...)绑定。
不用 @requestParam要求请求参数的名称和方法形参名一致方可绑定.

对于简单类型参数中的日期型,建议使用自定义参数绑定,对日期型数据个化定义日期的格式.

自定义参数绑定:建议使用Convertor进行参数绑定.

还可以绑定pojo、包装的pojo.

数据回显

需求

表单提交出现错误,重新回到表单,用户重新填写数据,刚才提交的参数在页面上回显.

对简单类型的数据回显

对商品修改数据回显:
注意在进入修改页面的controller方法中和提交修改商品信息方法model.addAttribute方法设置的key一致。

@RequestMapping("/editItemSubmit")
public String editItemSubmit(Model model,Integer id) throws Exception{
    model.addAttribute("id",id);
    ... 
}

pojo类型数据回显

方法一:

使用Model.addtribute方法进行数据回显:

@RequestMapping("/editItemSubmit")
public String editItemSubmit(Model model,Integer id,ItemCustom itemCustom) throws Exception{
    model.addAttribute("items",itemCustom);
    ... 
}

方法二:

使用@ModelAttribute,作用于将请求pojo数据放到Model中回显到页面

@RequestMapping("/editItemSubmit")
public String editItemSubmit(Model model,Integer id,@ModelAttribute(value="item") ItemCustom itemCustom) throws Exception{
    ... 
}

在ModelAttribute方法指定的名称就是要填充Model中的key,在页面中就要通过key取数据.

@ModelAttribute将方法返回值传到页面

    //单独将商品类型的方法提出来,将方法返回值填充到request,在页面显示
    @ModelAttribute("itemsType")
    public Map<String, String> getItemsType()throws Exception{      
        HashMap<String, String> itemsType = new HashMap<String,String>();
        itemsType.put("001", "数码");
        itemsType.put("002", "服装");
        return itemsType;       
    }

使用@ModelAttribute将公用的取数据的方法返回值传到页面,不用在每一个controller方法通过Model将数据传到页面.

参数绑定集合类型

绑定数组

需求:在商品查询列表页面,用户选择要删除的商品,批量删除商品。
在controller方法中如何将批量提交的数据绑定成数组类型。


jsp页面

controller

绑定List<Object>

需求:批量修改商品信息提交.
先进入批量修改商品页面,填写信息,点击提交.

页面定义



注释:
itemsList:controller方法形参包装类型中list的属性名。
itemsList[0]或itemsList[1]。。,[]中是序号,从0开始。
itemsList[].name:name就是controller方法形参包装类型中list中pojo的属性名

controller方法及包装类定义


统一异常处理

一般项目中都需要作异常处理,基于系统架构的设计考虑,使用统一的异常处理方法。

系统中异常类型有哪些?
包括预期可能发生的异常、运行时异常(RuntimeException),运行时异常不是预期会发生的。
针对预期可能发生的异常,在代码手动处理异常可以try/catch捕获,可以向上抛出。
针对运行时异常,只能通过规范代码质量、在系统测试时详细测试等排除运行时异常。

统一异常处理解决方案

定义异常

针对预期可能发生的异常,定义很多异常类型,这些异常类型通常继承于Exception。
这里定义一个系统自定义异常类:
CustomException,用于测试。

public class CustomException extends Exception {    
    //异常信息
    private String message; 
    public CustomException(String message){
        super(message);
        this.message = message;
        
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}
异常处理

要在一个统一异常处理的类中要处理系统抛出的所有异常,根据异常类型来处理。
1.定义统一异常处理器类
统一异常处理器实现HandlerExceptionResolver接口。

public class CustomExceptionResolver implements HandlerExceptionResolver  {

    //前端控制器DispatcherServlet在进行HandlerMapping、调用HandlerAdapter执行Handler过程中,如果遇到异常就会执行此方法
    //handler最终要执行的Handler,它的真实身份是HandlerMethod
    //Exception ex就是接收到异常信息
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {
        ...
     }
}

2.配置统一异常处理器

<!-- 定义统一异常处理器 -->
<bean class="cn.itcast.ssm.exception.CustomExceptionResolver"></bean>

3.异常处理逻辑
根据不同的异常类型进行异常处理。

系统自定义的异常类是CustomException ,在controller方法中、service方法中手动抛出此类异常。

针对系统自定义的CustomException异常,就可以直接从异常类中获取异常信息,将异常处理在错误页面展示。
针对非CustomException异常,对这类重新构造成一个CustomException,异常信息为“未知错误”,此类错误需要在系统测试阶段去排除。

在统一异常处理器CustomExceptionResolver中实现上边的逻辑。

public class CustomExceptionResolver implements HandlerExceptionResolver  {

    //前端控制器DispatcherServlet在进行HandlerMapping、调用HandlerAdapter执行Handler过程中,如果遇到异常就会执行此方法
    //handler最终要执行的Handler,它的真实身份是HandlerMethod
    //Exception ex就是接收到异常信息
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex) {
        //输出异常
        ex.printStackTrace();
        
        //统一异常处理代码
        //针对系统自定义的CustomException异常,就可以直接从异常类中获取异常信息,将异常处理在错误页面展示
        //异常信息
        String message = null;
        CustomException customException = null;
        //如果ex是系统 自定义的异常,直接取出异常信息
        if(ex instanceof CustomException){
            customException = (CustomException)ex;
        }else{
            //针对非CustomException异常,对这类重新构造成一个CustomException,异常信息为“未知错误”
            customException = new CustomException("未知错误");
        }
        
        //错误 信息
        message = customException.getMessage();
        
        request.setAttribute("message", message);

        
        try {
            //转向到错误 页面
            request.getRequestDispatcher("/WEB-INF/jsp/error.jsp").forward(request, response);
        } catch (ServletException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return new ModelAndView();
    }

}

4.测试抛出异常由统一异常处理器捕获
可以在controller方法、service方法、dao实现类中抛出异常,要求dao、service、controller遇到异常全部向上抛出异常,方法向 上抛出异常throws Exception


5.图解

前端控制器DispatcherServlet在进行HandlerMapping、调用HandlerAdapter执行Handler过程中,如果遇到异常,try/catch进行异常捕获,并调用异常处理器处理.

springmvc拦截器

拦截器的异常场合

用户请求到DispatherServlet中,DispatherServlet调用HandlerMapping查找Handler,HandlerMapping返回一个拦截的链儿(多个拦截),springmvc中的拦截器是通过HandlerMapping发起的。
在企业开发,使用拦截器实现用户认证(用户登陆后进行身份校验拦截),用户权限拦截。

springmvc拦截器方法

public class HandlerInterceptor1 implements HandlerInterceptor {

    //在执行handler之前来执行的
    //用于用户认证校验、用户权限校验
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
        
        System.out.println("HandlerInterceptor1...preHandle");
        
        //如果返回false表示拦截不继续执行handler,如果返回true表示放行
        return false;
    }
    //在执行handler返回modelAndView之前来执行
    //如果需要向页面提供一些公用 的数据或配置一些视图信息,使用此方法实现 从modelAndView入手
    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("HandlerInterceptor1...postHandle");
        
    }
    //执行handler之后执行此方法
    //作系统 统一异常处理,进行方法执行性能监控,在preHandle中设置一个时间点,在afterCompletion设置一个时间,两个时间点的差就是执行时长
    //实现 系统 统一日志记录
    @Override
    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("HandlerInterceptor1...afterCompletion");
    }

}

配置拦截器

配置全局的拦截器,DispatcherServlet将配置的全局拦截器加载到所有的HandlerMapping。

在springmvc.xml中配置:

<!--拦截器 -->
<mvc:interceptors>
    <!--多个拦截器,顺序执行 -->
    <mvc:interceptor>
        <mvc:mapping path="/**" />
        <bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor1"></bean>
    </mvc:interceptor>
    <mvc:interceptor>
        <mvc:mapping path="/**" />
        <bean class="cn.itcast.ssm.controller.interceptor.HandlerInterceptor2"></bean>
    </mvc:interceptor>
</mvc:interceptors>

测试

测试1 (1 号和2号都放行)
测试结果:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle

HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle

HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion

总结:
执行preHandle是顺序执行。
执行postHandle、afterCompletion是倒序执行

测试2(1 号放行和2号不放行)
测试结果:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion

总结:
如果preHandle不放行,postHandle、afterCompletion都不执行。
只要有一个拦截器不放行,controller不能执行完成

测试3 (1 号不放行和2号不放行)
测试结果:
HandlerInterceptor1...preHandle
总结:
只有前边的拦截器preHandle方法放行,下边的拦截器的preHandle才执行。

日志拦截器或异常拦截器要求

将日志拦截器或异常拦截器放在拦截器链儿中第一个位置,且preHandle方法放行.

拦截器应用(用户认证拦截)

需求
用户访问系统的资源(url),如果用户没有进行身份认证,进行拦截,系统跳转登陆页面,如果用户已经认证通过,用户可以继续访问系统 的资源。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348

推荐阅读更多精彩内容

  • 2017.11.11,也是来上海的两个月,就这样走上写日记的路吧! 不记得从什么时候开始,双十一成了全民节日特别是...
    众知阅读 268评论 1 1
  • 16002-郑云清 今天分享的绘本书名为《隧道》,由我非常喜欢的绘本作家-安东尼.布朗作著,这是一个关于手足亲情的...
    郑小乾_8eaa阅读 376评论 0 0
  • 清晨第一缕阳光照进来。你睁开眼,发现床边的人偶不见了。 人偶叫蛋蛋,与接地气的名字不符,他面容精致,身材...
    蛋蛋_二号机阅读 428评论 0 0
  • 1.开始前,请确认gcc g++开发类库是否装好,默认已经安装 centos平台编译环境使用如下指令 yum -y...
    054ab278d5d9阅读 391评论 0 1
  • 从来没有像现在这样感觉到时间的紧迫过,不知道从那一刻起,觉得自己输不起的竟然是时间,以前觉得人生顺其自然就好,殊不...
    嘉仪0918阅读 359评论 0 0