springmvc下的日志配置

springmvc下的日志配置,第1张

日志是开发一个系统必不可少的工具,所有问题的解决,最终依赖记录的日志去查询。

开发多年,spring的日志配置我都是复制了别人的配置,从未熟悉。最近梳理了一次。特留一份记录。

个人电脑是mac

java是18

使用idea开发。

日志这块使用了lombok插件。需要自己安装。

例如如下配置将会打印2次日志

删除其中一个stdout即可恢复正常。

初期我拷贝了别人的配置,日志的配置放在src/main/resources/config 下

然后配置如图

该配置通常能正常工作,但是在test时无法正常运行。

因此我修改了配置文件的路径。直接放入 src/main/resources 下。

在webxml也无需加载。强烈建议大家使用,不要放别的地方,增加了出现其他问题的概率。

一) 其实这个功能在spring2x时代就提供了。一直没用过,今天在spring-mvc32x的环境下试验了一次。还算简单易用。

二) 依赖。

spring依赖POI或jExcel来实现对excel输出的支持,前者是apache出品,貌似名气更大,本例使用第一个。

<dependency>

<groupId>orgapachepoi</groupId>

<artifactId>poi</artifactId>

<version>37</version>

</dependency>

三) spring提供了一个AbstractExcelView作为自己实现的视图的父类。实例代码如下。

package yingcarview;

import javatextDateFormat;

import javatextSimpleDateFormat;

import javautilList;

import javautilMap;

import javaxservlet>

import javaxservlet>

import orgapachepoihssfusermodelHSSFDataFormat;

import orgapachepoihssfusermodelHSSFSheet;

import orgapachepoihssfusermodelHSSFWorkbook;

import orgapachepoissusermodelCell;

import orgapachepoissusermodelCellStyle;

import orgapachepoissusermodelIndexedColors;

import orgjodatimeDateTime;

import orgslf4jLogger;

import orgslf4jLoggerFactory;

import orgspringframeworkwebservletviewdocumentAbstractExcelView;

import yingcarbindingDateRange;

import yingcardomainRefuelingRecord;

public class RefuelingRecordExcelView extends AbstractExcelView {

private static final Logger LOGGER = LoggerFactorygetLogger(RefuelingRecordExcelViewclass);

private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd");

@Override

@SuppressWarnings({"unchecked"})

protected void buildExcelDocument(

Map<String, Object> model,        // MVC中的M就在这里了

HSSFWorkbook workbook,

>

>

{

("yyyy/MM/dd"));

LOGGERdebug("end: {}", new DateTime(drgetEnd())toString("yyyy/MM/dd"));

}

}

HSSFSheet sheet = workbookcreateSheet(DATE_FORMATformat(drgetStart()) + "-" + DATE_FORMATformat(drgetEnd()));

setColumnsWidth(sheet);

fillTableHeader(workbook, sheet);

fillTableBody(workbook, sheet, rrl);

}

private void setColumnsWidth(HSSFSheet sheet) {

final int[] warr = new int[] {

500,  // <空>

4500, // 日期

4500, // 车辆

4500, // 燃油种类

4500, // 燃油单价

4500, // 加油方式

4500, // 加油量

3000, // 花费

12000  // 备注

};

for (int i = 0; i < warrlength; i ++) {

sheetsetColumnWidth(i, warr[i]);

}

}

// 填充表格头

private void fillTableHeader(HSSFWorkbook workbook, HSSFSheet sheet) {

final String[] contents = new String[] {

"日期",

"车辆",

"燃油种类",

"燃油单价(元/升)",

"加油方式",

"加油量(升)",

"花费(元)",

"备注"

};

int r = 1;

int c = 1;

CellStyle style = workbookcreateCellStyle();

stylesetFillForegroundColor(IndexedColorsYELLOWgetIndex());      // 填充**

stylesetFillPattern(CellStyleSOLID_FOREGROUND);           // 填充方式

// 设置border

stylesetBorderLeft(CellStyleBORDER_THIN);

stylesetBorderRight(CellStyleBORDER_THIN);

stylesetBorderTop(CellStyleBORDER_THIN);

stylesetBorderBottom(CellStyleBORDER_THIN);

for (int i = 0; i < contentslength; i ++) {

Cell cell = getCell(sheet, r, c + i);

cellsetCellValue(contents[i]);

cellsetCellStyle(style);

}

}

private void fillTableBody(HSSFWorkbook workbook, HSSFSheet sheet, List<RefuelingRecord> records) {

// 通用style

CellStyle style = workbookcreateCellStyle();

stylesetFillForegroundColor(IndexedColorsWHITEgetIndex());       // 填充白色

stylesetFillPattern(CellStyleSOLID_FOREGROUND);                   // 填充方式

stylesetBorderLeft(CellStyleBORDER_THIN);

stylesetBorderRight(CellStyleBORDER_THIN);

stylesetBorderTop(CellStyleBORDER_THIN);

stylesetBorderBottom(CellStyleBORDER_THIN);

// 日期style

CellStyle dateStyle = workbookcreateCellStyle();

dateStylesetFillForegroundColor(IndexedColorsWHITEgetIndex());       // 填充白色

dateStylesetFillPattern(CellStyleSOLID_FOREGROUND);                   // 填充方式

dateStylesetBorderLeft(CellStyleBORDER_THIN);

dateStylesetBorderRight(CellStyleBORDER_THIN);

dateStylesetBorderTop(CellStyleBORDER_THIN);

dateStylesetBorderBottom(CellStyleBORDER_THIN);

dateStylesetDataFormat(HSSFDataFormatgetBuiltinFormat("m/d/yy"));

int r = 2;

int c = 1;

Cell cell = null;

for (int i = 0; i < recordssize(); i ++) {

RefuelingRecord rr = recordsget(i);

// 日期

cell = getCell(sheet, r, c + 0);

if (rrgetDate() != null)

cellsetCellValue(rrgetDate());

cellsetCellStyle(dateStyle);

// 车辆

cell = getCell(sheet, r, c + 1);

if (rrgetVehicle()getNickname() != null)

cellsetCellValue(rrgetVehicle()getNickname());

cellsetCellStyle(style);

// 燃油种类

cell = getCell(sheet, r, c + 2);

if (rrgetGasType() != null) {

String s = null;

switch (rrgetGasType()) {

case _0: s  = "0号柴油"; break;

case _93: s = "93号汽油"; break;

case _97: s = "97号汽油"; break;

case _98: s = "98号汽油"; break;

}

cellsetCellValue(s);

}

cellsetCellStyle(style);

// 单价

cell = getCell(sheet, r, c + 3);

if (rrgetPriceOfGas() != null)

cellsetCellValue(rrgetPriceOfGas());

cellsetCellStyle(style);

// 加油方式

cell = getCell(sheet, r, c + 4);

if (rrgetRefuelingType() != null) {

String s = null;

switch (rrgetRefuelingType()) {

case FIXED_CUBAGE:

s = "固定容积"; break;

case FIXED_MONEY:

s = "固定金额"; break;

case FULL:

s = "加满"; break;

}

cellsetCellValue(s);

}

cellsetCellStyle(style);

// 加油量

cell = getCell(sheet, r, c + 5);

if (rrgetCubageOfGas() != null)

cellsetCellValue(rrgetCubageOfGas());

cellsetCellStyle(style);

// 花费

cell = getCell(sheet, r, c + 6);

if (rrgetSumOfMoney() != null)

cellsetCellValue(rrgetSumOfMoney());

cellsetCellStyle(style);

// 备注

cell = getCell(sheet, r, c + 7);

if (rrgetComment() != null)

cellsetCellValue(rrgetComment());

cellsetCellStyle(style);

r ++;

}

}

}

cellsetCellStyle(style);

// 燃油种类

cell = getCell(sheet, r, c + 2);

if (rrgetGasType() != null) {

String s = null;

switch (rrgetGasType()) {

case _0: s  = "0号柴油"; break;

case _93: s = "93号汽油"; break;

case _97: s = "97号汽油"; break;

case _98: s = "98号汽油"; break;

}

cellsetCellValue(s);

}

cellsetCellStyle(style);

// 单价

cell = getCell(sheet, r, c + 3);

if (rrgetPriceOfGas() != null)

cellsetCellValue(rrgetPriceOfGas());

cellsetCellStyle(style);

// 加油方式

cell = getCell(sheet, r, c + 4);

if (rrgetRefuelingType() != null) {

String s = null;

switch (rrgetRefuelingType()) {

case FIXED_CUBAGE:

s = "固定容积"; break;

case FIXED_MONEY:

s = "固定金额"; break;

case FULL:

s = "加满"; break;

}

cellsetCellValue(s);

}

cellsetCellStyle(style);

// 加油量

cell = getCell(sheet, r, c + 5);

if (rrgetCubageOfGas() != null)

cellsetCellValue(rrgetCubageOfGas());

cellsetCellStyle(style);

// 花费

cell = getCell(sheet, r, c + 6);

if (rrgetSumOfMoney() != null)

cellsetCellValue(rrgetSumOfMoney());

cellsetCellStyle(style);

// 备注

cell = getCell(sheet, r, c + 7);

if (rrgetComment() != null)

cellsetCellValue(rrgetComment());

cellsetCellStyle(style);

r ++;

}

}

}

四) Controller中返回逻辑视图名 (代码片段)

Java代码

@RequiresUser       // 安全框架用元注释

@RequiresRoles({"ROLE_USER"})

@RequestMapping(value = "/list/excel", method = RequestMethodGET)

public String listByExcel(

@DateRangeFormat(pattern = "yyyy-MM-dd") @RequestParam("dateRange") DateRange dateRange,

ModelMap modelMap

)

{

}

// 放入model

modelMapput("dateRange", dateRange);

modelMapput("refuelingRecordList", gasServicefindRefuelingRecordByDateRange(currentUserId, dateRange));

return "refueling-record-list"; // 最终返回逻辑视图名

}

五) 为spring-mvc配置多个视图解析器。

<bean class="orgspringframeworkwebservletviewXmlViewResolver">

<property name="order" value="1" /> <!-- order很重要 -->

<property name="location" value="classpath:/META-INF/viewsxml" />

</bean>

<bean class="orgspringframeworkwebservletviewInternalResourceViewResolver">

<property name="order" value="9999" />

<property name="viewClass" value="orgspringframeworkwebservletviewJstlView" />

<property name="prefix" value="/WEB-INF/jsp/"/>

<property name="suffix" value="jsp"/>

六) 效果图

先来总体说一下我对这个问题的理解,用一句话概括:

数据库是可以控制事务的传播和隔离级别的,Spring在之上又进一步进行了封装,可以在不同的项目、不同的 *** 作中再次对事务的传播行为和隔离级别进行策略控制。

注意:Spring不仅可以控制事务传播行为(PROPAGATION_REQUIRED等),还可以控制事务隔离级别(ISOLATION_READ_UNCOMMITTED等)。

(以下是个人理解,如果有瑕疵请及时指正)

下面我具体解释一下:

为了大家能够更好的理解,先来明确几个知识点:

事务的传播行为:简单来说就是事务是手动提交还是自动提交,事务什么时候开始,什么时候提交。

事务的隔离级别:简单来说,就四个,提交读,提交读,重复读,序列化读。

首先我来描述一下,数据库(mysql)层面上对于事务传播行为和隔离级别的配置和实验方法:

数据库层面(采用命令行):其实mySql命令行很简单,希望实验 *** 作一下:

//连接数据库,我这里是本地,后面是用户名密码,不要打分号,如果指令不行,配置下环境变量,网上有很多。

1 cmd中执行:mysql -hlocalhost -uroot -pmysql

//查看本地数据库事务传播行为是手动提交(0),还是自动提交(1)。

2select @@autocommit;

//如果是0,希望设置为手动提交,这里其实是设置本对话的autocommit,因为如果你再开一个cmd,发现还是没改回来,如果想修改全局的,网上有global方法。

3set @@autocommit=0;

//然后查询本地数据库中的一条记录,我本地数据库为test1;

4use test1;

5select from task where taskid=1;

//同时新开一个窗口cmd,连接数据库,并且修改这条记录,update语句我就不写了,或者直接修改数据库本条记录。

//再次执行select from task where taskid=1;发现值没变。OK因为此时数据库隔离级别为repeatable read 重复读,因为mysql默认的隔离级别是重复读。

//修改数据库隔离级别

6set global transaction isolation level read committed;

//查看一下,可能需要重新连接一下

7select @@tx_isolation;

//这时在执行一下4,5 *** 作,发现值变了,ok。因为已经改变了数据库隔离级别,发生了重复读出不同数据的现象。

(以上 *** 作希望有不明白的上网自学一下,很有用,先把数据库隔离级别弄明白了)

然后再来讲一下,Spring对事务传播行为和隔离级别的二次封装。

因为不同项目可能在一个mysql的不同数据库上,所以可以在项目中配置数据库的传播行为和隔离级别:

关于spring的传播行为(PROPAGATION_REQUIRED、PROPAGATION_REQUIRED等),我《数据库隔离级别(mysql+Spring)与性能分析 》文章中有讲,网上也有很多相关资料,我就不说了。

关于spring的事务隔离级别与数据库的一样,也是那四个,多了一个default,我也不仔细讲了。

下面主要讲一下spring的配置方法:

<property name="transactionAttributes">

<props>

<prop key="save">PROPAGATION_REQUIRED</prop>

<prop key="update">PROPAGATION_REQUIRED</prop>

<prop key="delete">PROPAGATION_REQUIRED</prop>

<prop key="get">PROPAGATION_REQUIRED,readOnly</prop>

<prop key="find">PROPAGATION_REQUIRED,ISOLATION_READ_UNCOMMITTED</prop>

</props>

就以find为例,可以配置这么配置,前面是控制传播行为,后面是控制事务隔离级别的。那么这时哪怕数据库层面上是重复读,但是还是以这里为准,你会发现在同一个事务中两次查询的结果是不一样的。

最后扫除一个盲区,readonly这个属性,是放在传播行为中的,一般书都这么归类,我也尝试了一下,readonly并不能影响数据库隔离级别,只是配置之后,不允许在事务中对数据库进行修改 *** 作,仅此而已。

1)在applicationContext里面配置Hibernate的dataSource和SessionFactory

2)编写Dao的接口是实现类。如果用到Spring的Hibernate的 *** 作模板(HibernateTemplate)可以继承HibernateDaoSupport,实现类注解成@Repository

3)编写Action,然后注解成@Controller,在Action里面需要用@Autowired注入Dao的实例

4)配置applicationContextxml,加上Spring

MVC的视图处理器

5)编写页面,然后提交请求。搞定!

以上就是关于springmvc下的日志配置全部的内容,包括:springmvc下的日志配置、springmvc excel表格数据导入数据库怎么做、spring mvc 怎么样设置mysql事物隔离级别等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/10146988.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-05
下一篇 2023-05-05

发表评论

登录后才能评论

评论列表(0条)

保存