SpringMvc入门到开发(四)之自定义异常处理,上传,自定义的参数类型转化【附详细截图】

所有资料打包下载:有需要的可以下载
http://download.csdn.net/download/xiaozhegaa/9907441

【分享资料】在注解那一篇说道,绑定数据(收集V传递到C的数据):绑定数组,绑定list,map,绑定podo等Springmvc的各种类型参数绑定 案例下载,里面有开发步骤跟截图,有需要的下载:
http://download.csdn.net/detail/xiaozhegaa/9906508

这里写图片描述

【总结:】在前面的SpringMvc入门到开发过程三篇文章中,我们已经学会了如何去配置核心配置文件(springmvc-config.xml)、如何配置前端控制器(DispatcherSevlet)、前端控制器的底层原理、如何去映射一个方法的路径(注解)、如何去获取页面传过来的数据(参数绑定)、如何去跨页面传递数据(Model,ModelMap,ModelAndView)、页面跳转(ModelAndView,记得没有讲过重定向,稍后把剩下没讲到杂七杂八的一并总结一篇咯)、如何获取数据(el表达式,老知识)等知识,就算不学习这一篇的文章,也可以去开发。写这一篇文章的目的,是介绍一下springmvc还提供一些其他的便捷的操作。在框架中一般会有提供“文件上传”,“验证码”,“异常处理”,“数据交互”等封装技术,接下来就来了解一下
一、自定义的参数类型转化
1、问题的描述:在收集数据的时候需要对数据进行一些特殊的处理。这个问题最常见的就是发生在,字符串到日期的一个转化问题。由于日期数据有很多种格式,springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定。【】当然不止日期这个转换,例如还有在收集数据前先对字符串进行去头尾空串处理,也算是转换的一种。这里以字符串转化成日期为例:
2:开发步骤如下

//1.首先在springmvc-config.xml中把
//<mvc:annotation-driven/>
//改成
<mvc:annotation-driven conversion-service="conversionService"/>
//注意conversionSercvice是自己定义的bean名称。
//2.自己写一个conversionService的Bean
<!-- 配置Conveter转换器 转换工厂(日期) -->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <!-- 自定义转换器的类(由我来写) -->
                <bean class="dgut.xiaozheng.hander.conversion.DateConveter" />
                <!-- 自定义去除字符串转换器-->
                <!--<bean class="...."-->
                <!--......这里可以写多个转换器-->
            </set>
        </property>
    </bean>

这里写图片描述

//3.自己去写一个DateConveter的类
/*
 * 日期转换的数据类
 * S:页面传递过来的类型
 * T:转化后的类型
 * */
public class DateConveter implements Converter<String, Date>{

    @Override
    public Date convert(String source) {
        try {
            // 把字符串转换为日期类型
            if(null!=source) {
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                //转化成功后把结果返回。这里可以通过debug调试查看,或者在控制台打印输出
                return simpleDateFormat.parse(source);
            }

        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (java.text.ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // 如果转换异常则返回空
        return null;
    }
}
//测试案例
假设一个添加商品的表单,有一个输入时间的表单项name=createTime,使用User收集数据,有个Date类型的成员变量createTime。
    若没有写自定义转换器的时候,就会出错。因为String类型不能转化成Date类型
    若写了自定义转化器的时候,输入2071-07-22 10:57:06,就会成功。测试打印数据ok

这里写图片描述
【注意:】在写DateConveter类的时候,定义了字符串的格式为yyyy-MM-dd HH:mm:ss ,所以你的格式一定要是2071-07-22 10:57:06,如果你是自己的格式,修改一下就可以了。那么…………至此,自定义参数类型转化就没问题了

二、 异常处理器
1、问题的描述:springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。
2、底层原理:
这里写图片描述
3、开发步骤
3.1、自定义异常类:需要继承异常处理类的接口
3.2、按照提示实例化接口的方法

//【注意这里的HandlerExceptionResolver 包不要导错了】
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
/**
 * 异常处理器的自定义的实现类
 * @author xiaozheng
 */
public class CustomerExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, 
            Object handler,
            Exception e) {
        //以下两句是打印异常日记。在eclipse可以通过控制台看出,但是在linux上一定要打印出来,这里我就不写日志代码
        //日志    1.发布 tomcat war  Eclipse  
        //2.发布Tomcat  服务器上  Linux  Log4j

        /*
        * 分析:返回值为ModelAndView ,故实例化一个ModelAndView。并且设置返回的视图。
        * 为了测试:在ModelAndView中,添加一个错误提示
        */
        ModelAndView mav = new ModelAndView();
        mav.addObject("error", "测试异常处理");
        mav.setViewName("error");
    return mav;
}

3.3、需要在核心配置文件中去配置该bean

//class根据自己的异常处理类路径来修改
<bean class="dgut.xiaozheng.hander.Exception.CustomerExceptionResolver"></bean>

3.4、测试

    //测试步骤1:写一个注册的表单页面,提交到"/register"方法
    //测试步骤2:在“/register”故意出错,int i = 10 / 0 ;

这里写图片描述

    //测试步骤3:写一个error.jsp页面。获取数据就可以了
    ${error }

结果显示:【可见我们的配置是生效了】
这里写图片描述
接下来,演示一下自定义异常处理类。开发步骤是一样的,核心代码截图给大家。

//修改更改的地方

//1:在CustomerExceptionResolver 中,使用 instanceof 判断是哪种异常
ModelAndView mav = new ModelAndView();
    //判断异常为类型,MessageException是我们定义的。e表示我们抛出去的异常
    if(e instanceof MessageException){
        //预期异常
        MessageException me = (MessageException)e;
        mav.addObject("error", me.getMsg());
    }else{
        mav.addObject("error", "未知异常");
    }
    mav.setViewName("error");
    return mav;

//2: 新建一个自己的异常处理类MessageException
public class MessageException extends Exception{
    private String msg;

    public MessageException(String msg) {
        super();
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

//3:在“/register”中把Message抛出
//假设这里去查找用户列表
    List<User> userList = new ArrayList<User>();
    //这里写的是userList == null才会抛出错误,但是这只是为了演示,直接把userList看成是空的,故写null == null,让它一定会抛出该错误
    if(null == null) {
        throw new MessageException("用户列表不能为空");

    }

结果显示:

这里写图片描述
【扩展】这样子,你就可以定义任意多个异常处理类,在异常处理类中写错误信息,然后在异常控制器类中通过判断抛出的错误类型,调用视图查看错误信息。【值得注意的是:】异常处理器类跟异常处理类是不一样的的。前者是需要时间处理器类接口,在核心配置文件中配置,后者只是我们写的普通的异常类而已,那么………………自此我们就学会了自定义异常处理器类

三:文件上传
问题引入:如果说,直接在项目的WEB-INF下面建立一个upload文件夹,上传的文件实际是存储在tomcat里面的upload,而非项目的upload文件夹,可以项目中的upload在本机是可以看到里面的文件。但是一旦把项目打包发给别人的时候,就会出现缺少图片的错误。因为你的图片并没有打包过去。所以这里推荐是在自己的电脑上新建一个虚拟目录,上传到虚拟目录上,然后再一起打包给别人
1、先扩展一个虚拟目录的知识。
【what】什么是虚拟目录?建立虚拟目录之后,可以通过某个地址在浏览器访问得到。可以理解成站点
【how】 有两种方式,第一种是在tomcat上配置虚拟站点

//在tomcat上配置图片虚拟目录,在tomcat下conf/server.xml中添加:
< Context docBase="D:\develop\upload\temp" path="/pic" reloadable="false"/>

第二种方式在eclipse里面配置。具体步骤截图如下。
这里写图片描述

这里写图片描述
复制一张图片到存放图片的文件夹,使用浏览器访问
测试效果,如下图:

这里写图片描述
【注意】有些人做了以上的操作之后会访问不到文件,原因是你没有保存,你应该把文件关闭,关闭的时候提示你是否保存,你保存后,再重启服务器就可以了。上述无关上传的事情,等会做显示的时候有可能会用到。接下来讲真正上传
开发步骤:
1、加入jar包

//上传必备包,稍后会一起打包发给大家的
commons-fileupload-1.2.2.jar
commons-io-2.4.jar

2、在springmvc.xml中配置文件上传解析器

<!-- 文件上传,id必须设置为multipartResolver -->
<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 设置文件上传大小 5M = 5 * 1024 * 1024 具体值自己算-->
    <property name="maxUploadSize" value="5000000" />
</bean>

3、写一个上传的jsp表单,并且修改以二进制的方式提交数据

//核心代码
 enctype="multipart/form-data"
 <input type="file" name="pictureFile">

这里写图片描述
4、图片上传方法中,

总结MultipartFile(文件上传类常用的方法)

byte[] getBytes():获取文件数据
String getContentType():获取文件MIME类型,如image/jpg\
InputStream getInputStream():获取文件流
String getName():获取上传组件中name的名字
String getOriginalFilename():获取文件上传的原名
long getSize():获取文件大小,单位字节
Boolean isEmpty():是否上传文件
void transferTo(File dest):将上传的文件保存到一个目标文件中

/*上传的文件会自动绑定到MultipartFile中*/
public String myUpload(MultipartFile pictureFile,ModelMap model) throws IllegalStateException, IOException{
        if(!pictureFile.isEmpty()){
            //生成UUID,并且把-去掉
            String name = UUID.randomUUID().toString().replaceAll("-", "");
            //获取文件的真实名称
            //pictureFile.getOriginalFilename()
            //获得文件的后缀名FilenameUtils.getExtension()是上传工具包方法
            //FilenameUtils.getExtension(pictureFile.getOriginalFilename());

            //根据你的要求来选择,这里保存的是图片的uuid+具体名称
            //获得图片的名称
            String realName =  pictureFile.getOriginalFilename();
            //transferTo的函数,就是保存函数的方法
            pictureFile.transferTo(new File("D:\\upload\\"+name+ext));

            //这里可以做一些其他的操作
            //例如保存路径到数据库。设置items的image值,然后进行更新
            //vo.getItems().setImage(name + "." + ext);
            //itemService.updateItemsById(vo.getItems());

            model.addAttribute("message", "上传图片成功");
            return "content/upload";
        }else{
            /*没有上传文件*/
            throw new NoUploadPictureException("没有文件");
        }

    }

5、显示图片这一块。模拟从数据库中查找出imageUrl

//在上传的时候,把url存到域对象中
pictureFile.transferTo(new File("D:\\upload\\"+name+ext));
//以下这句话是模拟从数据库里面查找,找到之后存储到Model中
model.addAttribute("message", name+ext);

在jsp页面上:

<!--注意,这里实际上,src访问的路径是 http://localhost:8080/pic/${requestScope.message}路径哦
也就是我之前配置的虚拟站点起了作用-->
<div>显示图片</div>
<img src="/pic/${requestScope.message }">

6、显示结果

这里写图片描述
那么那么…………………自此我们已经学会了文件上传

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值