SSM中的一些常用工具

1 篇文章 0 订阅
1 篇文章 0 订阅

SSM中的一些常用工具

日志处理

依赖导入

<!--slf4j+log4j依赖-->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.25</version>
</dependency>

配置log4j.properties文件

这个是我所配置的,详细的配置文档说明参考博文:Log4j框架配置文件log4j.properties配置使用详解

#   1. DEBUG (the least serious) 调试
#   2. INFO  hibernaer.sql
#   3. WARN  警告
#   4. ERROR 异常
#   5. FATAL (the most serious) 内存溢出
#定义LOG输出级别
log4j.rootLogger=INFO,Console,File,error,DEBUG
#定义日志输出目的地为控制台
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
#可以灵活地指定日志输出格式,下面一行是指定具体的格式
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n
log4j.appender.Console.Threshold = debug

#文件大小到达指定尺寸的时候产生一个新的文件
log4j.appender.File = org.apache.log4j.RollingFileAppender
#指定输出目录
log4j.appender.File.File = logs/cloneZjrt.log
#定义文件最大大小
log4j.appender.File.MaxFileSize = 100MB
# 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志
log4j.appender.File.Threshold = ALL
log4j.appender.File.layout = org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n


log4j.appender.error=org.apache.log4j.DailyRollingFileAppender
#指定输出目录
log4j.appender.error.file = logs/error.log
#后缀可为.txt  /  .log  /  .html等等,此处设置为时间格式滚动生成日志
log4j.appender.error.DatePattern='.'yyyy-MM-dd
# 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志
log4j.appender.error.Threshold = ERROR
log4j.appender.error.layout = org.apache.log4j.PatternLayout
log4j.appender.error.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n
log4j.appender.error.append=true

#输出DEBUG信息到指定文件
log4j.appender.DEBUG=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DEBUG.layout=org.apache.log4j.PatternLayout
log4j.appender.DEBUG.layout.ConversionPattern=[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n
log4j.appender.DEBUG.datePattern=yyyy-MM-dd'.log'
log4j.appender.DEBUG.Threshold = DEBUG
log4j.appender.DEBUG.append=true
log4j.appender.DEBUG.File=logs/debug.log

#打印sql语句,log4j.logger.com.cloneZjrt.dao=DEBUG这一条的com.cloneZjrt.dao需对应自己项目的包
log4j.logger.com.cloneZjrt.dao=DEBUG
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

测试

/**
 * Created by Administrator on 2020-1-23.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({"classpath:applicationContext.xml"})
public class TestDAO {

    private final Logger LOG = LoggerFactory.getLogger(this.getClass());

    @Test
    public void testLog(){

        LOG.info("info================");
        List<String> list = new ArrayList<>();
        try{
            System.out.println(list.get(1));
        }catch (Exception e){
            System.out.println(e.getMessage());
            LOG.error(e.getMessage(), e);
        }
    }
}

补充

若要实现打印运行的Sql语句,需在工程的mybatis-config.xml加入

<settings>
    <!--日志打印SQL语句-->
    <setting name="logImpl" value="LOG4J" />
</settings>

参考博文:SSM框架下log4j的配置和使用

文件操作

依赖的导入

<!--文件上传相关开始-->
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.4</version>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>

<!--excel导出-->
<dependency>
  <groupId>net.sourceforge.jexcelapi</groupId>
  <artifactId>jxl</artifactId>
  <version>2.6.12</version>
</dependency>

<!--文件上传相关结束-->

SpringMVC的XML文件的配置

<!--上传文件 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="defaultEncoding" value="UTF-8"/>
    <!-- 最大文件大小,-1为不限制大小 ,这里是100000000-->
    <property name="maxUploadSize" value="10000000"/>
    <!-- 最大内存大小 -->
    <property name="maxInMemorySize" value="10240"/>
</bean>

操作

这里实现两个例子,一个是文件的上传,一个是Excel文件的导出

/**
 * Created by Apple on 2020/2/12.
 */
@Controller
@RequestMapping("/file")
@ResponseBody
public class FileUploadController {

    @Resource
    private UserService userService;

    private final Logger LOG = LoggerFactory.getLogger(this.getClass());

    /**
     * 文件上传方法,多个文件
     * @param file
     * @return
     */
    @RequestMapping(value = "/upload", method = {RequestMethod.POST})
    public String updateItems(@RequestParam("file")MultipartFile file, HttpServletRequest request) {
        /**
         * 把图片保存到图片目录下,保存图片,避免文件名可能会重复,所以为每个文件生成一个新的文件名
         */
        try{
            String uuid = UUID.randomUUID().toString();
            // 截取文件的扩展名(如.jpg)
            String oriName = file.getOriginalFilename();
            String extName = oriName.substring(oriName.lastIndexOf("."));
            String fileName = uuid+extName;

            /**
             * 这里的aa可以获得当前工程运行目录,并建立一个upload文件夹
             * 这样的缺点是,重新部署(即版本更新)会造成文件丢失
             * 所以可以根据自己的业务需求,将aa改成固定的文件服务器地址
             */
            String aa = request.getServletContext().getRealPath("/upload/") + fileName;
            File filePath = new File(aa);
            System.out.println(aa);
            if (filePath.exists()){
                throw new LogicException("文件已存在");
            }
            if (!filePath.getParentFile().exists()) {
                filePath.getParentFile().mkdirs();
                System.out.println("创建目录" + filePath);
            }
            try {
                OutputStream os = new FileOutputStream(filePath);
                byte[] bytes = file.getBytes();
                os.write(bytes);
                os.flush();
                os.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }catch (Exception e){
            return "error";
        }
        return "success";
    }

    @RequestMapping(value = "/getExcel", method = {RequestMethod.GET})
    public String cwExcel(HttpServletRequest request) {

        String aa = request.getServletContext().getRealPath("/upload/") + UUID.randomUUID().toString() + ".xls";

        try {
            WritableWorkbook wwb = null;
            File filePath = new File(aa);
            if (!filePath.getParentFile().exists()) {
                filePath.getParentFile().mkdirs();
                System.out.println("创建目录" + filePath);
            }
            wwb = Workbook.createWorkbook(filePath);
            WritableSheet ws=wwb.createSheet("user",0);
            Label userId=new Label(0,0,"ID");
            Label userName=new Label(1,0,"姓名");
            ws.addCell(userId);
            ws.addCell(userName);
            List<UserEntity> userEntities = userService.findAll();
            for (int i = 0; i < userEntities.size(); i++) {
                //Label labelId_i=new Label(0,i+1,String.valueOf(workLogEntities.get(i).getUserid()));
                Label labelId_i=new Label(0,i+1,String.valueOf(userEntities.get(i).getUserId()));
                Label labelmall_i=new Label(1,i+1,userEntities.get(i).getUserName());
                ws.addCell(labelId_i);
                ws.addCell(labelmall_i);
            }
            wwb.write();
            wwb.close();
        } catch (Exception e){
            e.printStackTrace();
        }
        return aa;
    }

}

可参考博文:springmvc文件上传操作

自定义异常

实现自定义异常类主要继承以下三个父类

Throwable:是所有异常信息的父类,Exception是从Throwable派生出来的,包括了包括Exception(异常)和Error(错误),定义所有可以作为异常被抛出来的类。

Exception:受检查的异常,这种异常是强制我们catch或throw的异常,专指程序本身可以处理的异常,一般性的异常。遇到这种异常必须进行catch或throw,如果不处理,编译器会报错,比如:IOException。‘

RuntimeException:运行时异常,这种异常我们不需要处理,完全由虚拟机接管。比如我们常见的NullPointerException,我们在写程序时不会进行catchthrowRuntimeException也是继承自Exception的,只是虚拟机对这两种异常进行了区分。

一般性的自定义异常继承RuntimeException即可。

简单使用

这里博主写一个BusinessException的异常类

@Data
public class BusinessException extends RuntimeException {
    private static final long serialVersionUID = -2780823944154925080L;
    private Long errorCode;//错误代码
    private String msg;//错误信息

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

    public BusinessException(String message, Long errorCode) {
        super(message);
        this.msg = message;
        this.errorCode = errorCode;
    }
}

测试

在测试类中进行测试

@Test
    public void testException() throws Exception {
        new BusinessException("文件已存在",415l).printStackTrace();
    }

控制台报以下错,可以直接定位错误位置

BusinessException(errorCode=415, msg=文件已存在)
	at com.cloneZjrt.TestDAO.testOne(TestDAO.java:20)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

ControllerAdvice全局异常处理

这里博主用自定义异常实现一个ControllerAdvice异常处理器

作用:注解ControllerAdviceRestControllerAdvice提供了对controller注解下方法发生异常之后的全局处理功能

@ExceptionHandler:全局异常捕获,捕获到指定异常后处理。通常用作获取异常后统一返回结构化的错误信息

@InitBinder:指定参数名,获取的参数绑定变量前的自定义操作,不如给时间日期增加解析器,构建不同的变量名头部信息。

@ModelAttribute:该方法返回的值可以在controller中接收。

/**
 * 拦截异常统一处理器
 * Created by Apple on 2020/2/21.
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private Logger LOG = Logger.getLogger(GlobalExceptionHandler.class);
    /**
     * 业务异常统一处理
     * @param req
     * @param bx
     * @return
     */
    @ExceptionHandler(value = BusinessException.class)
    public ResultInfo notFoundErrorHandler(HttpServletRequest req, BusinessException bx) {
        LOG.error(bx);
        ResultInfo info = new ResultInfo();
        info.fail();
        //TODO 扩展错误编码
        info.setState("50001");
        info.setMsg(bx.getMessage());
        return info;
    }

    /**
     * 位置异常统一处理
     * @param req
     * @param ex
     * @return
     */
    @ExceptionHandler(value = RuntimeException.class)
    public ResultInfo defaultErrorHandler(HttpServletRequest req, RuntimeException ex) {
        // 其他异常处理逻辑...
        LOG.error(ex);
        ResultInfo info = new ResultInfo();
        info.fail();
        info.setMsg(ex.getMessage());
        return info;
    }
}

写一个测试类,测试运行

@Controller
@ResponseBody
public class TestController {

    @GetMapping(value = "/test")
    public String test(){
        List<String> strings = new ArrayList<>();
        try{
            return strings.get(2);
        }catch (Exception e){
            throw e;
        }
    }
}

可以看到返回以下的数据,格式是自定义的Json格式,并且把错误信息置入msg中,说明这里发生的异常是经过全局异常处理之后返回的结果,证明自定义异常处理已经成功实现。

{
    "success": false,
    "state": "500",
    "msg": "Index: 2, Size: 0",
    "datas": null
}

参考博文:ControllerAdvice增强器

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值