文章目录
ssm依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<spring.version>5.0.3.RELEASE</spring.version>
<druid.version>1.1.2</druid.version>
<jstl.version>1.2</jstl.version>
<servlet-api.version>4.0.0</servlet-api.version>
<jsp-api.version>2.3.1</jsp-api.version>
<commons-fileupload.version>1.3.3</commons-fileupload.version>
<ehcache.version>2.10.4</ehcache.version>
<slf4j.version>1.7.25</slf4j.version>
<mybatis.version>3.4.5</mybatis.version>
<pagehelper.version>4.2.1</pagehelper.version>
<mybatis-ehcache.version>1.0.0</mybatis-ehcache.version>
<mybatis-generator-core.version>1.3.5</mybatis-generator-core.version>
<maven-plugin-api.version>3.5.0</maven-plugin-api.version>
<mybatis.spring.version>1.3.1</mybatis.spring.version>
<jackson.version>2.9.0</jackson.version>
<shiro.version>1.4.0</shiro.version>
</properties>
<dependencies>
<!--org.aspectj aop注解-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.10</version>
</dependency>
<!-- 缓存 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>${ehcache.version}</version>
</dependency>
<!--mysql驱动包 换成自己对于版本mysql驱动包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>${jsp-api.version}</version>
<scope>provided</scope>
</dependency>
<!-- 文件上传组件 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons-fileupload.version}</version>
</dependency>
<!--单元测试jar-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!--spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring web依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring整合ORM框架依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 日志处理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!--mybatis分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>${pagehelper.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>${mybatis-ehcache.version}</version>
</dependency>
<!--mybatis spring 集成jar-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis.spring.version}</version>
</dependency>
<!-- mybatis反向建模 -->
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven-plugin-api.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>${mybatis-generator-core.version}</version>
</dependency>
<!--json处理-->
<!--实际上为三个包,但是导入databind会自动导入其他两个包-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
<build>
<finalName>ssm</finalName>
<plugins>
<!--mybatis代码生成插件-->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.5</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
<!--配置资源打包方式-->
<resources>
<resource>
<!-- 配置打war时候的要打的文件路径 -->
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<!--包含文件夹以及子文件夹下所有资源-->
<include>**/*.*</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
ssm 配置文件
spring.xml / springmvc.xml / mybatis.xml
jdbc.properties
jdbc 反向生成工具 generatorConfig.xml
日志: log4j.properties
web.xml 配置 spring 和 springmvc
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<!-- ssm 整合, web.xml 中只需要
读取 springmvc 配置文件
配置 编码过滤器 ,前端控制器
读取 spring.xml 配置文件
通过 全局配置,指定 日志文件的位置 日志记录刷新时间 / spring 配置文件的位置
配置监听器 读取 spring.xml 配置文件,监听全局配置
还剩 mybatis.xml jdbc.properties 配置文件 统一交给 spring.xml 配置文件进行配置即可
-->
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--全局配置-->
<!--指定 spring 配置文件的地址-->
<context-param>
<param-name>contextConfigLocation</param-name>
<!--如果 spring 配置文件有多个,都是作为spring 配置文件,配置 spring 的功能,那么可以写
统一可以区分的前缀 然后加上 * 表示任意的后缀,读取所有的 spring 配置文件
-->
<!-- <param-value>classpath*:abc*.xml</param-value>-->
<param-value>classpath*:spring.xml</param-value>
</context-param>
<!--指定log4j 配置文件的地址-->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath*:log4j.properties</param-value>
</context-param>
<!--log4j日志记录刷新时间-->
<context-param>
<param-name>log4jRefreshInterval</param-name>
<!--1min 刷新一次-->
<param-value>60000</param-value>
</context-param>
<!--配置springmvc-->
<!--配置编码过滤器-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--spring 监听器 用于读取 spring 配置文件 监听全局配置的地址-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--配置核心控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--读取配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springmvc.xml</param-value>
</init-param>
<!--服务器启动时初始化-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--过滤带后缀的请求-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--可以和 spring 无缝整合-->
<!--扫描 不要 和 spring 扫描重复了
springmvc 扫描 controller 层
实际开发的时候,多人做不同的模块,会出现 com.sc.AA.controller
com.sc.BB.controller ,
在扫描包的时候要注意 com.sc.AA.controller,com.sc.BB.controller
-->
<context:component-scan base-package="com.sc.controller"/>
<!--开启注解驱动 mvc 后缀的-->
<mvc:annotation-driven/>
<!--放行静态资源-->
<mvc:default-servlet-handler/>
<!--视图解析器-->
<!--上传组件做上传下载-->
<!--拦截器做权限-->
</beans>
spring.xml 整合 mybatis
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--扫描: spring 只扫描业务层
控制层: springmvc 负责扫描
-->
<context:component-scan base-package="com.sc.service"/>
<!--spring 配置事务管理方式-->
<!--1,加载 jdbc 配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--2.创建数据源==>连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!--连接池的额外配置-->
<!--设置初始连接大小-->
<property name="initialSize" value="5"/>
<!--最小连接数-->
<property name="minIdle" value="5"/>
<!--最大连接数-->
<property name="maxActive" value="20" />
<!--配置最大等待时间 1min-->
<property name="maxWait" value="600000"/>
<!--配置最大空闲时间 5min-->
<property name="minEvictableIdleTimeMillis" value="300000"/>
<!--连接空闲超过时,验证连接是否可用 开启 和 验证-->
<property name="testWhileIdle" value="true"/>
<property name="validationQuery" value="select 1"/>
</bean>
<!--3.配置事务管理类(相当于底层写了一个环绕通知 开启 提交 回滚)-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--4. 注解做事务,开启注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!--spring 整合 mybatis
读取了 spring 配置文件,就会读取 mybatis 核心配置文件 和 映射文件
-->
<!--1.整合 mybatis 配置文件-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
<!--关联mybatis映射文件-->
<property name="configLocation" value="classpath:mybatis.xml"/>
<!--关联mybatis 映射文件-->
<property name="mapperLocations" value="classpath:com/sc/mapper/*.xml"/>
<!--
如果是 分模块写项目 mapper 包 地址是不同的
-->
<!-- 方式一: 通过 , 分隔多个包-->
<!-- <property name="mapperLocations" value="classpath:com/sc/AA/mapper/*.xml,classpath:com/sc/BB/mapper/*.xml"/>-->
<!--方式二: 通过数组的形式 分别编写-->
<!--<property name="mapperLocations" >
<array>
<value>classpath:com/sc/AA/mapper/*.xml</value>
<value>classpath:com/sc/BB/mapper/*.xml</value>
<value>classpath:com/sc/CC/mapper/*.xml</value>
<value>classpath:com/sc/DD/mapper/*.xml</value>
</array>
</property>-->
</bean>
<!--2.整合mybatis 中的 mapper 接口 动态创建 mapper 接口实现类-->
<!-- service 层就可以直接注入 mapper 接口-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入 sqlsession 工厂 需要工厂 bean 名称 字符串类型 不需要 ref-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--提供 mapper 接口的包-->
<property name="basePackage" value="com.sc.mapper"/>
</bean>
</beans>
mybatic.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--创建 file 文件,复制约束-->
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--1. 设置属性 -->
<settings>
<!--sql 执行日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!--2.分页插件, (可以给 spring 整合,整合前后代码量一致)-->
<plugins>
<!--配置分页插件 pageHelper-->
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="offsetAsPageNum" value="true" />
<property name="rowBoundsWithCount" value="true" />
<!--pageSize=0时,是否查询出全部结果,默认为false-->
<property name="pageSizeZero" value="true" />
<!--分页合理化参数,默认文false;pageNum<=0,查询第一页;pageNum>总页数,查询最后一页-->
<property name="reasonable" value="true" />
<property name="params"
value="pageNum=pageHelperStart;pageSize=pageHelperRows;" />
<property name="supportMethodsArguments" value="false" />
<property name="returnPageInfo" value="none" />
</plugin>
</plugins>
</configuration>
mybatis 逆向工程 配置文件 generatorConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration>
<!--加载jdbc.properties配置文件-->
<properties resource="jdbc.properties"/>
<!--配置驱动jar包的位置-->
<classPathEntry location="${driverClassPath}"/>
<!--
context:生成一组对象的环境
id:必选,上下文id,用于在生成错误时提示
defaultModelType:指定生成对象的样式
1,conditional:类似hierarchical;
2,flat:所有内容(主键,blob)等全部生成在一个对象中;
3,hierarchical:主键生成一个XXKey对象(key class),Blob等单独生成一个对象,其他简单属性在一个对象中(record class)
targetRuntime:
1,MyBatis3:默认的值,生成基于MyBatis3.x以上版本的内容,包括XXXBySample;
2,MyBatis3Simple:类似MyBatis3,只是不生成XXXBySample;
introspectedColumnImpl:类全限定名,用于扩展MBG
-->
<context id="context1" targetRuntime="MyBatis3">
<!-- genenat entity时,生成toString -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<!-- generate entity时,生成serialVersionUID -->
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
<!--不生成注释-->
<commentGenerator>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--配置数据库连接信息-->
<jdbcConnection driverClass="${jdbc.driver}"
connectionURL="${jdbc.url}" userId="${jdbc.username}" password="${jdbc.password}"/>
<!-- java模型创建器,是必须要的元素
负责:1,key类(见context的defaultModelType);2,java类;3,查询类
targetPackage:生成的类要放的包,真实的包受enableSubPackages属性控制;
targetProject:目标项目,指定一个存在的目录下,生成的内容会放到指定目录中,如果目录不存在,MBG不会自动建目录
-->
<!--生成实体类,一定要换成自己项目的包-->
<javaModelGenerator targetPackage="com.sc.pojo"
targetProject="src/main/java">
<!-- 设置是否在getter方法中,对String类型字段调用trim()方法 -->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 生成SQL map的XML文件生成器,
注意,在Mybatis3之后,我们可以使用mapper.xml文件+Mapper接口(或者不用mapper接口),
或者只使用Mapper接口+Annotation,所以,如果 javaClientGenerator配置中配置了需要生成XML的话,这个元素就必须配置
targetPackage/targetProject:同javaModelGenerator
-->
<!--生成映射文件:mapper-->
<!--ssm 整合后 mapper 接口 和 映射文件 要在同一个目录 否则 spring 找不到-->
<sqlMapGenerator targetPackage="com.sc.mapper"
targetProject="src/main/java"></sqlMapGenerator>
<!-- 对于mybatis来说,即生成Mapper接口,注意,如果没有配置该元素,那么默认不会生成Mapper接口
targetPackage/targetProject:同javaModelGenerator
type:选择怎么生成mapper接口(在MyBatis3/MyBatis3Simple下):
1,ANNOTATEDMAPPER:会生成使用Mapper接口+Annotation的方式创建(SQL生成在annotation中),不会生成对应的XML;
2,MIXEDMAPPER:使用混合配置,会生成Mapper接口,并适当添加合适的Annotation,但是XML会生成在XML中;
3,XMLMAPPER:会生成Mapper接口,接口完全依赖XML;
注意,如果context是MyBatis3Simple:只支持ANNOTATEDMAPPER和XMLMAPPER
-->
<!--生成 mapper 接口,之前的 dao 接口,-->
<javaClientGenerator targetPackage="com.sc.mapper"
targetProject="src/main/java" type="XMLMAPPER"/>
<!-- 需要逆向 enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"
-->
<!--注:如果之前已经添加了对于的 实体类 映射文件,不要重复添加
否则:实体类,会还原 mapper 接口也会还原 映射文件 会追加
以后生成哪个表信息,只需要,写表名即可
-->
<table tableName="o_role" enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false">
</table>
<table tableName="o_admin" enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false">
</table>
<table tableName="o_menu" enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false">
</table>
</context>
</generatorConfiguration>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/sc220501?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&rewriteBatchedStatement=true&serverTimezone=GMT
jdbc.username=root
jdbc.password=root
# idea 连接 mysql 驱动地址
driverClassPath=F:\\seecen\\jar\\mysql-connector-java-5.1.44-bin.jar
log4j.properties
#生产环境使用info
#log4j.rootLogger = info,stdout,logfile
#开发环境使用debug
log4j.rootLogger = info,stdout,logfile
log4j.logger.com.seecen.system.aop.advice = trace,aop
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %p [%C].%M(%L) --> %m%n
log4j.appender.logfile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.Threshold = ERROR
log4j.appender.logfile.DatePattern='.'yyyy-MM-dd
log4j.appender.logfile.File = D:/ssmlogfile.log
log4j.appender.logfile.layout = org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %p [%C].%M(%L) --> %m%n
log4j.appender.logfile.Append=true
log4j.appender.aop = org.apache.log4j.DailyRollingFileAppender
log4j.appender.aop.File = D:/ssmlogfileAOP.log
log4j.appender.aop.layout = org.apache.log4j.PatternLayout
log4j.appender.aop.layout.ConversionPattern =%d{yyyy-MM-dd HH\:mm\:ss} %m%n
log4j.appender.aop.Append=true
log4j.properties 配置说明
################################################################################
#①配置根Logger,其语法为:
#
#log4j.rootLogger = [level],appenderName,appenderName2,...
#level是日志记录的优先级,分为OFF,TRACE,DEBUG,INFO,WARN,ERROR,FATAL,ALL
##Log4j建议只使用四个级别,优先级从低到高分别是DEBUG,INFO,WARN,ERROR
#通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关
#比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来
#appenderName就是指定日志信息输出到哪个地方。可同时指定多个输出目的
################################################################################
################################################################################
#②配置日志信息输出目的地Appender,其语法为:
#
#log4j.appender.appenderName = fully.qualified.name.of.appender.class
#log4j.appender.appenderName.optionN = valueN
#
#Log4j提供的appender有以下几种:
#1)org.apache.log4j.ConsoleAppender(输出到控制台)
#2)org.apache.log4j.FileAppender(输出到文件)
#3)org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
#4)org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
#5)org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
#
#1)ConsoleAppender选项属性
# -Threshold = DEBUG:指定日志消息的输出最低层次
# -ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
# -Target = System.err:默认值System.out,输出到控制台(err为红色,out为黑色)
#
#2)FileAppender选项属性
# -Threshold = INFO:指定日志消息的输出最低层次
# -ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
# -File = C:\log4j.log:指定消息输出到C:\log4j.log文件
# -Append = FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容
# -Encoding = UTF-8:可以指定文件编码格式
#
#3)DailyRollingFileAppender选项属性
# -Threshold = WARN:指定日志消息的输出最低层次
# -ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
# -File = C:\log4j.log:指定消息输出到C:\log4j.log文件
# -Append = FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容
# -DatePattern='.'yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。还可以按用以下参数:
# '.'yyyy-MM:每月
# '.'yyyy-ww:每周
# '.'yyyy-MM-dd:每天
# '.'yyyy-MM-dd-a:每天两次
# '.'yyyy-MM-dd-HH:每小时
# '.'yyyy-MM-dd-HH-mm:每分钟
# -Encoding = UTF-8:可以指定文件编码格式
#
#4)RollingFileAppender选项属性
# -Threshold = ERROR:指定日志消息的输出最低层次
# -ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
# -File = C:/log4j.log:指定消息输出到C:/log4j.log文件
# -Append = FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容
# -MaxFileSize = 100KB:后缀可以是KB,MB,GB.在日志文件到达该大小时,将会自动滚动.如:log4j.log.1
# -MaxBackupIndex = 2:指定可以产生的滚动文件的最大数
# -Encoding = UTF-8:可以指定文件编码格式
################################################################################
################################################################################
#③配置日志信息的格式(布局),其语法为:
#
#log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
#log4j.appender.appenderName.layout.optionN = valueN
#
#Log4j提供的layout有以下几种:
#5)org.apache.log4j.HTMLLayout(以HTML表格形式布局)
#6)org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
#7)org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
#8)org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
#9)org.apache.log4j.xml.XMLLayout(以XML形式布局)
#
#5)HTMLLayout选项属性
# -LocationInfo = TRUE:默认值false,输出java文件名称和行号
# -Title=Struts Log Message:默认值 Log4J Log Messages
#
#6)PatternLayout选项属性
# -ConversionPattern = %m%n:格式化指定的消息(参数意思下面有)
#
#9)XMLLayout选项属性
# -LocationInfo = TRUE:默认值false,输出java文件名称和行号
#
#Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下:
# %m 输出代码中指定的消息
# %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
# %r 输出自应用启动到输出该log信息耗费的毫秒数
# %c 输出所属的类目,通常就是所在类的全名
# %t 输出产生该日志事件的线程名
# %n 输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”
# %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式
# 如:%d{yyyy年MM月dd日 HH:mm:ss,SSS},输出类似:2012年01月05日 22:10:28,921
# %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数
# 如:Testlog.main(TestLog.java:10)
# %F 输出日志消息产生时所在的文件名称
# %L 输出代码中的行号
# %x 输出和当前线程相关联的NDC(嵌套诊断环境),像java servlets多客户多线程的应用中
# %% 输出一个"%"字符
#
# 可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
# %5c: 输出category名称,最小宽度是5,category<5,默认的情况下右对齐
# %-5c:输出category名称,最小宽度是5,category<5,"-"号指定左对齐,会有空格
# %.5c:输出category名称,最大宽度是5,category>5,就会将左边多出的字符截掉,<5不会有空格
# %20.30c:category名称<20补空格,并且右对齐,>30字符,就从左边交远销出的字符截掉
################################################################################
################################################################################
#④指定特定包的输出特定的级别
#log4j.logger.org.springframework=DEBUG
################################################################################
#OFF,systemOut,logFile,logDailyFile,logRollingFile,logMail,logDB,ALL
log4j.rootLogger =ALL,systemOut,logFile,logDailyFile,logRollingFile,logMail,logDB
#输出到控制台
log4j.appender.systemOut = org.apache.log4j.ConsoleAppender
log4j.appender.systemOut.layout = org.apache.log4j.PatternLayout
log4j.appender.systemOut.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n
log4j.appender.systemOut.Threshold = DEBUG
log4j.appender.systemOut.ImmediateFlush = TRUE
log4j.appender.systemOut.Target = System.out
#输出到文件
log4j.appender.logFile = org.apache.log4j.FileAppender
log4j.appender.logFile.layout = org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n
log4j.appender.logFile.Threshold = DEBUG
log4j.appender.logFile.ImmediateFlush = TRUE
log4j.appender.logFile.Append = TRUE
log4j.appender.logFile.File = ../Struts2/WebRoot/log/File/log4j_Struts.log
log4j.appender.logFile.Encoding = UTF-8
#按DatePattern输出到文件
log4j.appender.logDailyFile = org.apache.log4j.DailyRollingFileAppender
log4j.appender.logDailyFile.layout = org.apache.log4j.PatternLayout
log4j.appender.logDailyFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n
log4j.appender.logDailyFile.Threshold = DEBUG
log4j.appender.logDailyFile.ImmediateFlush = TRUE
log4j.appender.logDailyFile.Append = TRUE
log4j.appender.logDailyFile.File = ../Struts2/WebRoot/log/DailyFile/log4j_Struts
log4j.appender.logDailyFile.DatePattern = '.'yyyy-MM-dd-HH-mm'.log'
log4j.appender.logDailyFile.Encoding = UTF-8
#设定文件大小输出到文件
log4j.appender.logRollingFile = org.apache.log4j.RollingFileAppender
log4j.appender.logRollingFile.layout = org.apache.log4j.PatternLayout
log4j.appender.logRollingFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n
log4j.appender.logRollingFile.Threshold = DEBUG
log4j.appender.logRollingFile.ImmediateFlush = TRUE
log4j.appender.logRollingFile.Append = TRUE
log4j.appender.logRollingFile.File = ../Struts2/WebRoot/log/RollingFile/log4j_Struts.log
log4j.appender.logRollingFile.MaxFileSize = 1MB
log4j.appender.logRollingFile.MaxBackupIndex = 10
log4j.appender.logRollingFile.Encoding = UTF-8
#用Email发送日志
log4j.appender.logMail = org.apache.log4j.net.SMTPAppender
log4j.appender.logMail.layout = org.apache.log4j.HTMLLayout
log4j.appender.logMail.layout.LocationInfo = TRUE
log4j.appender.logMail.layout.Title = Struts2 Mail LogFile
log4j.appender.logMail.Threshold = DEBUG
log4j.appender.logMail.SMTPDebug = FALSE
log4j.appender.logMail.SMTPHost = SMTP.163.com
log4j.appender.logMail.From = xly3000@163.com
log4j.appender.logMail.To = xly3000@gmail.com
#log4j.appender.logMail.Cc = xly3000@gmail.com
#log4j.appender.logMail.Bcc = xly3000@gmail.com
log4j.appender.logMail.SMTPUsername = xly3000
log4j.appender.logMail.SMTPPassword = 1234567
log4j.appender.logMail.Subject = Log4j Log Messages
#log4j.appender.logMail.BufferSize = 1024
#log4j.appender.logMail.SMTPAuth = TRUE
#将日志登录到MySQL数据库
log4j.appender.logDB = org.apache.log4j.jdbc.JDBCAppender
log4j.appender.logDB.layout = org.apache.log4j.PatternLayout
log4j.appender.logDB.Driver = com.mysql.jdbc.Driver
log4j.appender.logDB.URL = jdbc:mysql://127.0.0.1:3306/xly
log4j.appender.logDB.User = root
log4j.appender.logDB.Password = 123456
log4j.appender.logDB.Sql = INSERT INTOT_log4j(project_name,create_date,level,category,file_name,thread_name,line,all_category,message)values('Struts2','%d{yyyy-MM-ddHH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')
批量修改后缀 html -> jsp
将脚本放到需要修改的文件的包中,双击执行
ren *.html *.jsp
批量添加指令,配置忽略 el
ctrl + shift + r
批量替换 <doctype!>
== >
<%@ page language="java" import="java.util.*" pageEncoding="utf-8" isELIgnored="false" %>
配置拦截器 设置项目前缀 path
// 目的:存储一次项目前缀
@WebFilter("/*")
public class MyFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
// 存储一次项目前缀
ServletContext application = filterConfig.getServletContext();
application.setAttribute("path",application.getContextPath());
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(servletRequest,servletResponse);
}
public void destroy() {
}
}
常用工具类
做验证码
示例:
前端
<%--验证码 要向后台发送一个请求,返回一个图片 项目前缀/getCode
拼接 this.src=this.src+'?d='+Math.random() 让请求地址不同
防止: 单击验证码,发送请求相同出现缓存
--%>
<img src="${path}/getCode" class="pull-right" id="captcha" style="cursor: pointer;" οnclick="this.src=this.src+'?d='+Math.random();" title="点击刷新" alt="captcha">
后端
/**
* 返回验证码图片
*/
@RequestMapping("/getCode")
public void getCode(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException, IOException {
// 产生一个验证码放到 session 中
CodeUtil.processRequest(request, response);
String code = (String) session.getAttribute("randomCode");
System.out.println(code);
}
工具类
package com.sc.util;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/**
* 描述:
* 验证码生成工具类
* @author bigpeng
* @create 2019-06-23 17:10
*/
public class CodeUtil {
private static int imgWidth = 100; // 图片宽度
private static int imgHeight = 50; // 图片高度
private static int codeCount = 4; // 验证码长度
private static int x = imgWidth / (codeCount + 1);
private static int fontHeight=imgHeight - 2;
private static int codeY=imgHeight - 12;
private static String fontStyle;
public static void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("image/jpeg");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0L);
HttpSession session = request.getSession();
BufferedImage image = new BufferedImage(imgWidth, imgHeight, 1);
Graphics2D g = image.createGraphics();
Random random = new Random();
g.setColor(Color.WHITE);
g.fillRect(0, 0, imgWidth, imgHeight);
g.setFont(new Font(fontStyle, 2, fontHeight));
g.setColor(new Color(55, 55, 12));
g.setColor(getRandColor(160, 200));
int red;
int green;
int blue;
int r;
//绘制干扰线 ==> 防止机器识别
for(int i = 0; i < 60; ++i) {
red = random.nextInt(imgWidth);
green = random.nextInt(imgHeight);
blue = random.nextInt(12);
r = random.nextInt(12);
g.drawLine(red, green, red + blue, green + r);
}
//生成随机验证码
String sRand = "";
for(int i = 0; i < codeCount; ++i) {
red = random.nextInt(255);
green = random.nextInt(255);
blue = random.nextInt(255);
int wordType = random.nextInt(3);
char retWord = 0;
switch(wordType) {
case 0:
retWord = getSingleNumberChar();
break;
case 1:
retWord = getLowerOrUpperChar(0);
break;
case 2:
retWord = getLowerOrUpperChar(1);
}
//随机生成的4位验证码
sRand = sRand + String.valueOf(retWord);
g.setColor(new Color(red, green, blue));
g.drawString(String.valueOf(retWord), i * x, codeY);
}
//将验证码保存session
session.setAttribute("randomCode", sRand);
g.dispose();
//验证码写到前端
ServletOutputStream responseOutputStream = response.getOutputStream();
ImageIO.write(image, "JPEG", responseOutputStream);
responseOutputStream.flush();
responseOutputStream.close();
}
/**
* 随机获取颜色
* @param fc
* @param bc
* @return
*/
private static Color getRandColor(int fc, int bc) {
Random random = new Random();
if (fc > 255) {
fc = 255;
}
if (bc > 255) {
bc = 255;
}
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
/**
* 获取随机数
* @return
*/
private static char getSingleNumberChar() {
Random random = new Random();
int numberResult = random.nextInt(10);
int ret = numberResult + 48;
return (char)ret;
}
/**
* 获取随机字母
* @param upper
* @return
*/
private static char getLowerOrUpperChar(int upper) {
Random random = new Random();
int numberResult = random.nextInt(26);
int ret = 0;
if (upper == 0) {
ret = numberResult + 97;
} else if (upper == 1) {
ret = numberResult + 65;
}
return (char)ret;
}
}
Md5 加密
package com.sc.util;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5 {
public static void main(String[] args) {
String str=MD5Code("abcd");
System.out.println("加密后:"+str);
//性能最优 支持3位以下 字母数字下划线密码解密
// MD5.back(str);
// System.out.println("解密后:"+result);
}
public static String MD5Code(String content) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
try {
byte[] byteArray = content.getBytes("UTF-8");
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(byteArray);
byte[] digest = messageDigest.digest();
int length = digest.length;
char str[] = new char[length * 2];
int k = 0;
for (int i = 0; i < length; i++) {
byte mData = digest[i];
str[k++] = hexDigits[mData >>> 4 & 0xf];
str[k++] = hexDigits[mData & 0xf];
}
return new String(str);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("不支持hash算法:MD5",e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("不支持UTF-8编码",e);
}
}
private static final char code[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', '_','0', '1', '2', '3', '4', '5',
'6', '7', '8', '9' };
public static String result;
public static void back(String md5){
StringBuilder testPW;
for(int a=0;a<code.length;a++){
testPW=new StringBuilder();
testPW.append(code[a]);
if(getResult(testPW.toString(),md5)) return;
for(int b=0;b<code.length;b++){
testPW=new StringBuilder(testPW.substring(0,1));
testPW.append(code[b]);
if(getResult(testPW.toString(),md5)) return;
for(int c=0;c<code.length;c++){
testPW=new StringBuilder(testPW.substring(0,2));
testPW.append(code[c]);
if(getResult(testPW.toString(),md5)) return;
// for(int d=0;d<code.length;d++){
// testPW=new StringBuilder(testPW.substring(0,3));
// testPW.append(code[d]);
// if(getResult(testPW.toString(),md5)) return;
// }
}
}
}
}
public static boolean getResult(String testPW,String md5){
if(md5.equalsIgnoreCase(MD5.MD5Code(testPW))){
result=testPW;
return true;
}
return false;
}
}
计划