项目架构简介
后端包(java.com.esms.*)
-
controller层
controller层是用来接受前台数据和返回页面请求信息的,
Controller层是不允许直接操作数据库的!它就像一个服务员,哪桌客人需要点菜了,就喊一声服务员!
对应的,外界需要完成什么样的业务,就通过Controller去调用不同的Service,需要记住的是Controller只是一个中间者或者转发者,不应该在Controller里暴露Service的业务逻辑,而应该直接转发Service的业务处理结果!
控制层,负责具体模块的业务流程控制,需要调用service逻辑设计层的接口来控制业务流程。
controller通过接收前端H5或者App传过来的参数进行业务操作,再将处理结果返回到前端。 -
dao层
entity就是属性类,通常定义在model层里面,相当于MVC的M层,属于数据模型层。一般得实体类对应一个数据表,其中的属性定义数据表中的字段,实体类的字段数量 >= 数据库表中需要操作的字段数量。这里用dao层定义了实体层的作用,而原本dao层应该写的接口写在了mapper层中。
-
exception
异常指不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程。Java通 过API中Throwable类的众多子类描述各种不同的异常。因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的 错误条件。当条件生成时,错误将引发异常。
Java异常类层次结构图:
在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性。
Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。
**Error(错误)😗*是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。
**Exception(异常)😗*是程序本身可以处理的异常。
Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。
注意:异常和错误的区别:异常能被程序本身可以处理,错误是无法处理。
通常,Java的异常(包括Exception和Error)分为可查的异常(checked exceptions)和不可查的异常(unchecked exceptions)。
可查异常(编译器要求必须处置的异常):正确的程序在运行中,很容易出现的、情理可容的异常状况。可查异常虽然是异常状况,但在一定程度上它的发生是可以预计的,而且一旦发生这种异常状况,就必须采取某种方式进行处理。
除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。
不可查异常(编译器不要求强制处置的异常):包括运行时异常(RuntimeException与其子类)和错误(Error)。
Exception 这种异常分两大类运行时异常和非运行时异常(编译异常)。程序中应当尽可能去处理这些异常。
**运行时异常:**都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
**非运行时异常 (编译异常):**是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
2.处理异常机制
在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常。
抛出异常:当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。
捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适 的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适 的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。
对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不同。
由于运行时异常的不可查性,为了更合理、更容易地实现应用程序,Java规定,运行时异常将由Java运行时系统自动抛出,允许应用程序忽略运行时异常。
对于方法运行中可能出现的Error,当运行方法不欲捕捉时,Java允许该方法不做任何抛出声明。因为,大多数Error异常属于永远不能被允许发生的状况,也属于合理的应用程序不该捕捉的异常。
对于所有的可查异常,Java规定:一个方法必须捕捉,或者声明抛出方法之外。也就是说,当一个方法选择不捕捉可查异常时,它必须声明将抛出异常。
能够捕捉异常的方法,需要提供相符类型的异常处理器。所捕捉的异常,可能是由于自身语句所引发并抛出的异常,也可能是由某个调用的方法或者Java运行时 系统等抛出的异常。也就是说,一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的。
任何Java代码都可以抛出异常,如:自己编写的代码、来自Java开发环境包中代码,或者Java运行时系统。无论是谁,都可以通过Java的throw语句抛出异常。
从方法中抛出的任何异常都必须使用throws子句。
捕捉异常通过try-catch语句或者try-catch-finally语句实现。
总体来说,Java规定:对于可查异常必须捕捉、或者声明抛出。允许忽略不可查的RuntimeException和Error。
-
interceptor
Interceptor 拦截器,是SpringMVC提供的,用来拦截Controller层方法的拦截器,和 Filter 过滤器的作用类型类似;
不同的是:拦截器 Interceptor 主要进行记录日志,判断用户是否登录,过滤权限(没有登录就跳转登录之类的);而过滤器则对全局进行过滤,主要用于编码过滤,统一编码
拦截器 interceptor :用来拦截Controller控制器的方法,主要用于实现权限分配,对没有权限的用户进行拦截(例如:购物车,只有登录了才能查看)。
【注意】一般请求都是先通过过滤器filter过滤,才会被拦截器 interceptor 处理,决定是否放行,两个过程有任何一个不放行,都不能访问到Controller层方法拦截器的主要方法
preHandle() :这个方法在业务处理器处理请求之前被调用,可以在此方法中做一些权限的校验。如果程序员决定该拦截器对请求进行拦截处理后还要调用其他的拦截器,或者是业务处理器去进行处理,则返回true;如果程序员决定不需要再调用其他的组件去处理请求,则返回false。
postHandle() :这个方法在业务处理器处理请求之后,渲染视图之前调用。在此方法中可以对ModelAndView中的模型和视图进行处理。
afterCompletion() :这个方法在 DispatcherServlet 完全处理完请求后被调用(即视图渲染完成之后),可以在该方法中进行一些资源清理的操作。 -
mapper层
mapper层(数据持久化层,专门用来跟数据库打交道的)。
mapper层用于和数据库交互,想要访问数据库并且操作,只能通过mapper层向数据库发送sql语句,将这些结果通过接口传给service层,对数据库进行数据持久化操作,他的方法语句是直接针对数据库操作的,主要实现一些增删改查操作,在mybatis中方法主要与与xxx.xml内相互一一映射。
而service层是针对controller层,也就是针对我们使用者。service的impl是把mapper和service进行整合的文件。 -
service层
用途:Service层主要负责业务模块的逻辑应用设计
首先设计接口,设计其实现的类,在Spring的配置文件中配置其实现的关联,这样就可以在应用中调用Service接口来进行业务处理,业务实现:具体要调用到已经定义的DAO接口,封装Service层的业务逻辑有利于业务逻辑的独立性和重复利用性,程序显得简洁。
Service层存放业务逻辑处理,也是一些关于数据库处理的操作,但不是直接和数据库打交道,它有接口还有接口的实现方法,在接口的实现方法中需要导入Mapper层,Mapper层是直接跟数据库打交道的,它也是个接口,只有方法名字,具体实现在Mapper.xml文件里,Service是提供我们使用的方法。 -
utils层
Util是工具的意思,一般来说,常常用来描述和业务逻辑没有关系的数据处理。
Util一般要和私有方法对比:私有方法一般来说是只是在特地场景下使用的,私有方法越多,代码结构越乱。常见的重构策略就是首先从一个越长行数的代码里抽象出若干个私有方法,然后再抽出公用的Util。
如果有可能,尽可能的少用私有方法,而是把他换成一个公用的Util,代表他和业务逻辑是不相关的。通常命名也是ArticleUtil,CommentUtil之类的。
某种程度上也会跟Service有点接近。但是Service一般而言,都是包含有业务逻辑的,很少能做单元测试。
Util一般来说,就是一个明确的输入和一个明确的输出结果。单元测试中,多数也是来测试Util。
-
vo层
View Object,视图层,其作用是将指定页面的展示数据封装起来,通常用于业务层之间的数据传递。类似于将前端页面传输的数据在后端service层封装成一个VO类,控制层需要调用时,直接调用该类中的属性,以获取各种数据。vo, 是controller和视图层(view)打交道,要和页面中的数据结构相同更方便。dto是service与dao 数据持久层交互的。
配置文件包(java.resources.*)
1.mappers层
这一层主要就是mybatis的应用。MyBatis 是一款优秀的持久层Dao框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的POJOs(Java实体类)映射成数据库中的记录.
要使用*.xml配置文件,首先要配置mybatis的xml文件,即mybatis-config.xml。
2.applicationContext.xml
1.applicationContext.xml配置文件在web项目中的作用
spring容器创建,数据注入,连接数据库,引入外部数据文件
以及其他对数据交互、连接外部服务的功能,这些功能是完成SSM框架对web项目作用的基础
2.applicationContext.xml配置文件的组成部分
表头header
<?xml version="1.0" encoding="UTF-8"?>
version——声明xml版本号
encoding——声明xml传输数据编码
UTF-8——声明编码格式
3.beans实例声明(本项目)
<?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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 对基本包进行注解扫描,开启注解 -->
<context:component-scan base-package="com.esms">
<!-- 只对controller进行扫描 -->
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- Spring的配置文件,这里主要配置和业务逻辑有关的 -->
<!--=================== 数据源,事务控制,xxx ================ -->
<!-- 加载数据库配置文件dbconfig.properties -->
<context:property-placeholder location="classpath:dbconfig.properties" />
<!-- 加载数据库 -->
<bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--================== 配置和MyBatis的整合=============== -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 指定mybatis全局配置文件的位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<property name="dataSource" ref="pooledDataSource"></property>
<!-- 指定mybatis,mapper文件的位置 -->
<property name="mapperLocations" value="classpath:mappers/*.xml"></property>
</bean>
<!-- 配置扫描器,将mybatis接口的实现加入到ioc容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 扫描所有dao接口的实现,加入到ioc容器中 -->
<property name="basePackage" value="com.esms.mapper"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<!-- 配置一个可以执行批量的sqlSession -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
<constructor-arg name="executorType" value="BATCH"></constructor-arg>
</bean>
<!-- ===============事务控制的配置 ================ -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--控制住数据源 -->
<property name="dataSource" ref="pooledDataSource"></property>
</bean>
<!--配置事务增强,事务如何切入 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="list*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="query*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="count*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="update*" read-only="false" propagation="REQUIRED"/>
<tx:method name="insert*" read-only="false" propagation="REQUIRED"/>
<tx:method name="save*" read-only="false" propagation="REQUIRED"/>
<tx:method name="delete*" read-only="false" propagation="REQUIRED"/>
<tx:method name="remove*" read-only="false" propagation="REQUIRED"/>
<tx:method name="*" read-only="true" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!--开启基于注解的事务,使用xml配置形式的事务(必要主要的都是使用配置式) -->
<aop:config>
<!-- 切入点表达式 --> <!-- 需要修改包的扫描 -->
<aop:pointcut expression="execution(* com.esms.service.impl.*.*(..))" id="txPoint" />
<!-- 配置事务增强 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint" />
</aop:config>
<bean class="com.esms.exception.CustomExceptionResolver"/>
</beans>
解释:
【xmlns=“http://www.springframework.org/schema/beans”】
声明xml文件默认的命名空间,表示未使用其他命名空间的所有标签的默认命名空间。
【xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”】
声明XML Schema实例,声明后就可以使用schemaLocation属性。
【xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd】
指定Schema的位置这个属性必须结合命名空间使用。这个属性有两个值,第一个值表示需要使用的命名空间。第二个值表示供命名空间使用的XML schema的位置。
上面配置的命名空间指定xsd规范文件,这样你在进行下面具体配置的时候就会根据这些xsd规范文件给出相应的提示,比如说每个标签是怎么写的,都有些什么属性是都可以智能提示的,在启动服务的时候也会根据xsd规范对配置进行校验。
配置技巧:对于属性值的写法是有规律的,中间使用空格隔开,后面的值是前面的补充,也就是说,前面的值是去除了xsd文件后得来的。
3.dbconfig.properties
Properties文件是java中很常用的一种配置文件,文件后缀为“.properties”,属文本文件,文件的内容格式是“键=值”的格式,可以用“#”作为注释,java编程中用到的地方很多,运用配置文件,可以便于java深层次的解耦。下面贴一份保存数据库连接字符串的properties配置文件
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/ssm_esms?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=true&verifyServerCertificate=false&autoReconnct=true&autoReconnectForPools=true&allowMultiQueries=true
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.user=root
jdbc.password=Wxy20010802@
这样我们就可以通过加载properties配置文件来连接数据库,达到深层次的解耦目的。
4.log4j.properties和log4j2.xml的区别
log4j是Apache的一个开源项目,log4j2和log4j是一个作者,只不过log4j2是重新架构的一款日志组件,他抛弃了之前log4j的不足,以及吸取了优秀的logback的设计重新推出的一款新组件。log4j2的社区活跃很频繁而且更新的也很快。
1、配置文件类型
log4j是通过一个.properties的文件作为主配置文件的,而现在的log4j 2则已经弃用了这种方式,采用的是.xml,.json或者.jsn这种方式来做,可能这也是技术发展的一个必然性,毕竟properties文件的可阅读性真的是有点差。
2、核心JAR包
log4j只需要引入一个jar包即可,
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
而log4j 2则是需要2个核心
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.5</version>
</dependency>
log4j和log4j 2的包路径是不同的,Apache为了区分,包路径都更新了
3、文件渲染
log4j想要生效,我们需要在web.xml中进行配置,
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:config/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>
这段配置目的在于告诉工程去哪加载log4j的配置文件和定义一个扫描器,这样可以随心所欲的放置log4j配置文件。
log4j2就比较简单,以maven工程为例,我们只需要把log4j2.xml放到工程resource目录下就行了。大家记住一个细节点,是log4j2.xml,而不是log4j.xml,xml名字少个2都不行!!
4、Log调用
log4j和log4j2调用都是很简单的。
import org.apache.log4j.Logger;
private final Logger LOGGER = Logger.getLogger(Test.class.getName());
log4j2:
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
private static Logger logger = LogManager.getLogger(Test.class.getName());
5、配置文件方式
最关键的最大的不同,那就是配置文件的区别了,大家具体使用的时候再根据你的情况进行配置就行了。
log4j(本项目未使用)
#1.\u539F\u7248\uFF08\u8BE6\u7EC6\uFF09
#log4j.rootLogger=DEBUG,myConsole
#log4j.appender.myConsole=org.apache.log4j.ConsoleAppender
#log4j.appender.myConsole.ImmediateFlush=true
#log4j.appender.myConsole.Target=System.out
#log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout
#log4j.appender.myConsole.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
#
#log4j.logger.com.mchange.v2=ERROR
#2.\u7B80\u7565\u7248
#
#log4j.rootLogger=DEBUG, stdout
#log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
log4j2 (本项目):
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" />
</Console>
<RollingFile name="RollingFile" filename="log/test.log"
filepattern="${logPath}/%d{YYYYMMddHHmmss}-fargo.log">
<PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" />
<Policies>
<SizeBasedTriggeringPolicy size="10 MB" />
</Policies>
<DefaultRolloverStrategy max="20" />
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console" />
<AppenderRef ref="RollingFile" />
</Root>
</Loggers>
</Configuration>
5.mybatis-config.xml
mybatis-config.xml是MyBatis核心配置文件,该文件配置了MyBatis的一些全局信息,包含数据库连接信息和Mybatis运行时所需的各种特性,以及设置和影响Mybatis行为的一些属性。
Mybatis核心配置文件结构
configuration配置
properties 可以配置在Java属性配置文件中
settings 修改Mybatis在运行时的行为方式
typeAliases 为Java类型命名一个别名(简称)
typeHandlers 类型处理器
objectFactory 对象工厂
plugins 插件
environments 环境
environment 环境变量
transactionManager 事务管理器
dataSource 数据源
mappers 映射器
配置文件讲解
configuration
configuration元素是整个XML配置文件的根节点,相当于MyBatis的总管,MyBatis所有的配置信息都会存放在这里面。Mybatis提供了设置这些配置信息的方法。Configuration可从配置文件里获取属性值,也可以通过程序直接设置。
properties元素
properties元素描述的都是外部化、可替代的属性
1.通过外部指定的方式(通过在典型Java属性配置文件 如database.properties)
database.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/smbms
user=root
password=root
mybatis-config.xml 引入database.properties
!--引入 database.properties 文件-->
<properties resource="database.properties"/>
……
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
</dataSource>
上述代码中,driver url username password属性将会用database.properties文件中的值来替换
2.直接配置为xml,并使用这些属性对配置项实现动态配置
mybatis-config.xml(本项目)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 是否开启自动驼峰命名规则 -->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!--开启懒加载-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--关闭积极加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!-- 定义别名 -->
<typeAliases>
<package name="com.esms.dao"/>
</typeAliases>
<!-- 引入分页插件 pagehelper -->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--分页参数合理化 防止出现-1页,或者超出最大页数-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
</configuration>
3.两种方式优先级
resource属性值的优先级高于property子节点配置的值
settings元素
settings元素的作用是设置一些非常重要的选项,用于设置和改变Mybatis运行中的行为
settings元素支持的属性
cacheEnabled : 对在此配置文件下的所有cache进行全局性开/关设置 - true|false
lazyLoadingEnabled : 全局性设置懒加载。如果设为false,则所有相关联的设置都会被初始化加载 -true|false
autoMappingBehavior : Mybatis对于resultMap自动映射的匹配级别 -PAPTLAL|NONE|FULL
type Aliases元素
配置类型别名,通过与MyBatis的SQL映射文件相关联,减少输入多余的完整类名,以简化操作
1.基础配置
<typeAliases>
<!--这里给实体类取别名,方便在mapper配置文件中使用-->
<typeAlias alias="user" type="cn.smbms.pojo.User"/>
<typeAlias alias="provider" type="cn.smbms.pojo.Provider"/>
……
</typeAliases>
2.简便配置
第一种方法弊端在于:如果一个项目中有多个POJO,需要一一进行配置。所以在第二种方法中,我们通过name属性直接指定包名,让Mybatis自动去扫描指定包下的JavaBean,并设置一个别名
<typeAliases>
<package name="cn.smbms.pojo"/>
</typeAliases>
<mapper namespace="cn.smbms.dao.user.User Mapper">
<!--查询用户表记录数-->
<select id="count" result Type="int">select count(1) as count from smbms_user
</select>
<!--查询用户列表-->
<select id="get User List" result Type="User">select * from smbms_user/select>
</mapper>
另外,Mybatis已经为许多常见的Java基础数据类型内建了相应的类型别名。一般都与其映射类型一致,并且都是大小写不敏感的,比如映射的类型int Boolean String Integer等,它们的别名都是int Boolean String Integer
environments元素
配置不同的运行环境
但是不管增加几套运行环境,都必须要明确选择出当前唯一的一个运行环境。这是因为每个数据库都对应一个Sql Session Factory实例,需要指明哪个运行环境被创建,并把运行环境中设置的参数传递个Sql Session Factory Builder
配置如下
<environments default="development">
<!--开发环境-->
<environment id="development">
<transaction Manager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
<!--测试环境-->
<environment id="test">
……
</environment>
</environments>
上述代码中,需要注意以下几个关键点:
(1)默认的运行环境ID:通过default属性来指定当前的运行环境ID为development,对于环境ID的命名要确保唯一。
(2)transactionManager事务管理器:设置其类型为JDBC(My Batis有两种事务管理类型,即JDBC和MANAGED),直接使用JDBC的提交和回滚功能,依赖于从数据源获得连接来管理事务的生命周期。
(3)dataSource元素:使用标准的JDBC数据源接口来配置JDBC连接对象的资源。My Batis提供了三种数据源类型UNPOOLED、POOLED、JNDI),这里使用POOLED数据源类型。该类型利用“池”的概念将JDBC连接对象组织起来,减少了创建新的连接实例时所必需的初始化和认证时间,是My Batis实现的简单的数据库连接池类型,它使数据库连接可被复用,不必在每次请求时都去创建一个物理连接。对于高并发的Web应用,这是一种流行的处理方式,有利于快速响应请求。
mappers
用来定义SQL的映射语句
1.使用类资源路径获取资源
<mappers>
<mapper resource="cn/smbms/dao/user/User Mapper.xml"/>
<mapper resource="cn/smbms/dao/provider/Provider Mapper.xml"/></mappers>
2.使用URL获取资源
<mappers>
<mapper url="file:///E:/sqlmappers/User Mapper.xml"/>
<mapper url="file:///E:/sqlmappers/Provider Mapper.xml"/>
</mappers>
6.springmvc-servlet.xml
web项目启动时,读取web.xml配置文件,首先解析的是applicationContext.xml文件,其次才是sping-mvc.xml文件,sping-mvc.xml文件中主要的工作是:
1.启动注解;
2.扫描controller包注解;
3.静态资源映射;
4.视图解析(defaultViewResolver);
5.文件上传(multipartResolver);
6.返回消息json配置
1.自动扫描
<!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->
<context:component-scan base-package="com.javen.controller" />
2.注解驱动
<!-- 扩充了注解驱动,可以将请求参数绑定到控制参数-->
<mvc:annotation-driven />
3.静态资源处理
<!-- 静态资源处理 css js images -->
<mvc:resources location="/resources/**" mapping="/resource/"/>
4.避免IE执行AJAX时,返回JSON出现下载文件
<!-- 避免IE执行AJAX时,返回JSON出现下载文件 -->
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
5.启动SpringMVC的注解功能,完成请求和注解POJO的映射
<!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJacksonHttpMessageConverter"/><!-- JSON转换器 -->
</list>
</property>
</bean>
6.配置文件上传
<!-- 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 默认编码 -->
<property name="defaultEncoding" value="utf-8" />
<!-- 上传文件最大值 -->
<property name="maxUploadSize" value="10485760000"/>
<!-- 内存中的最大值 -->
<property name="maxInMemorySize" value="40960"/>
<!-- 启用是为了推迟文件解析,以便捕获文件大小异常 -->
<property name="resolveLazily" value="true"/>
</bean>
7.配置viewResolver视图解析
<!-- 配置viewResolver。可以用多个viewResolver。使用order属性排序。InternalResourceViewResolver 放在最后 -->
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1"></property>
<property name="mediaTypes">
<map>
<!-- 告诉视图解析器,返回的类型为json格式 -->
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
<entry key="htm" value="text/htm" />
</map>
</property>
<property name="defaultViews">
<list>
<!-- ModelAndView里的数据变成JSON -->
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
<property name="ignoreAcceptHeader" value="true"></property>
</bean>
8.定义跳转的文件的前后缀 ,视图模式配置
<!-- 定义跳转的文件的前后缀 ,视图模式配置-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 这里的配置我的理解是自动给后面action的方法return的字符串加上前缀和后缀,变成一个 可用的url地址 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
本项目springmvc-servlet.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/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!--SpringMVC的配置文件,包含网站跳转逻辑的控制,配置 -->
<!--base-package:xxx(xxx.dao,xxx.controller)基础包 -->
<context:component-scan base-package="com.esms">
<!--只扫描控制器。 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--<context:component-scan base-package="com.esms.controller"></context:component-scan>-->
<!-- 视图解析器解析jsp解析,默认使用jstl标签,classpath下的得有jstl的包-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置页面路径的前缀 -->
<property name="prefix" value="/WEB-INF/page/"/>
<!-- 配置jsp路径的后缀 -->
<!--<property name="suffix" value=".html"/>-->
</bean>
<!--注解适配器和注解映射器-->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 防止静态资源被拦截 -->
<mvc:default-servlet-handler/>
<!--注册multipart解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"/>
<property name="maxUploadSize" value="1048576"/>
</bean>
<!-- 配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!-- <mvc:mapping path="/department/**"/>-->
<!-- <mvc:mapping path="/employee/**"/>-->
<!-- <mvc:mapping path="/monthlyattendance/**"/>-->
<!-- <mvc:mapping path="/toPage.do?url=admin/index.html"/>-->
<mvc:exclude-mapping path="/"/>
<mvc:exclude-mapping path="/static/**"/>
<mvc:exclude-mapping path="/img/**"/>
<mvc:exclude-mapping path="/WEB-INF/page/employee/login.html"/>
<mvc:exclude-mapping path="/WEB-INF/page/employee/index.html"/>
<mvc:exclude-mapping path="/WEB-INF/page/admin/adminLogin.html"/>
<mvc:exclude-mapping path="/WEB-INF/page/admin/superAdminLogin.html"/>
<mvc:exclude-mapping path="/ssm_esms/"/>
<mvc:exclude-mapping path="/admin.do"/>
<mvc:exclude-mapping path="/superAdmin.do"/>
<mvc:exclude-mapping path="/changeCode.do"/>
<mvc:exclude-mapping path="/employeeLogin.do"/>
<mvc:exclude-mapping path="/adminLogin.do"/>
<mvc:exclude-mapping path="/superAdminLogin.do"/>
<mvc:exclude-mapping path="/getAdminAccount.do"/>
<mvc:exclude-mapping path="/getEmployeeAccount.do"/>
<mvc:exclude-mapping path="/getSuperAdminAccount.do"/>
<bean class="com.esms.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
<mvc:default-servlet-handler />
</beans>
7.web.xml
一般的web工程中都会用到web.xml,web.xml主要用来配置,可以方便的开发web工程。web.xml主要用来配置Filter、Listener、Servlet等。但是要说明的是web.xml并不是必须的,一个web工程可以没有web.xml文件。
1、WEB工程加载web.xml过程
经过个人测试,WEB工程加载顺序与元素节点在文件中的配置顺序无关。即不会因为 filter 写在 listener 的前面而会先加载 filter。WEB容器的加载顺序是:ServletContext -> context-param -> listener -> filter -> servlet。并且这些元素可以配置在文件中的任意位置。
加载过程顺序如下:
启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取和两个结点。
紧急着,容创建一个ServletContext(servlet上下文),这个web项目的所有部分都将共享这个上下文。
容器将转换为键值对,并交给servletContext。
容器创建中的类实例,创建监听器。
2、web.xml文件元素详解
(1)schema
web.xml的模式文件是由Sun公司定义的,每个web.xml文件的根元素中,都必须标明这个 web.xml使用的是哪个模式文件。其它的元素都放在之中。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
</web-app>
(2)icon Web应用图标
指出IDE和GUI工具用来表示Web应用的大图标和小图标。
<icon>
<small-icon>/images/app_small.gif</small-icon>
<large-icon>/images/app_large.gif</large-icon>
</icon>
(3)display-name Web应用名称
提供GUI工具可能会用来标记这个特定的Web应用的一个名称
<display-name>Tomcat Example</display-name>
(4)disciption Web应用描述
给出于此相关的说明性文本
<disciption>Tomcat Example servlets and JSP pages.</disciption>
(5)context-param上下文参数
声明应用范围内的初始化参数。它用于向 ServletContext提供键值对,即应用程序上下文信息。我们的listener, filter等在初始化时会用到这些上下文中的信息。在servlet里面可以通过getServletContext().getInitParameter(“context/param”)得到。
<context-param>
<param-name>ContextParameter</para-name>
<param-value>test</param-value>
<description>It is a test parameter.</description>
</context-param>
(6)filter过滤器
将一个名字与一个实现javaxs.servlet.Filter接口的类相关联。
<filter>
<filter-name>setCharacterEncoding</filter-name>
<filter-class>com.myTest.setCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>setCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(7)listener监听器
<listener>
<listerner-class>com.listener.SessionListener</listener-class>
</listener>
(8)servlet
servlet 用来声明一个servlet的数据,主要有以下子元素:
servlet-name 指定servlet的名称
servlet-class 指定servlet的类名称
jsp-file 指定web站台中的某个JSP网页的完整路径
init-param 用来定义参数,可有多个init-param。在servlet类中通过getInitParamenter(String name)方法访问初始化参数
load-on-startup 指定当Web应用启动时,装载Servlet的次序。当值为正数或零时:Servlet容器先加载数值小的servlet,再依次加载其他数值大的servlet。当值为负或未定义:Servlet容器将在Web客户首次访问这个servlet时加载它。
servlet-mapping 用来定义servlet所对应的URL,包含两个子元素
url-pattern 指定servlet所对应的URL
<!-- 基本配置 -->
<servlet>
<servlet-name>snoop</servlet-name>
<servlet-class>SnoopServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>snoop</servlet-name>
<url-pattern>/snoop</url-pattern>
</servlet-mapping>
<!-- 高级配置 -->
<servlet>
<servlet-name>snoop</servlet-name>
<servlet-class>SnoopServlet</servlet-class>
<init-param>
<param-name>foo</param-name>
<param-value>bar</param-value>
</init-param>
<run-as>
<description>Security role for anonymous access</description>
<role-name>tomcat</role-name>
</run-as>
</servlet>
<servlet-mapping>
<servlet-name>snoop</servlet-name>
<url-pattern>/snoop</url-pattern>
</servlet-mapping>
(9)session-config会话超时配置
单位为分钟。
<session-config>
<session-timeout>120</session-timeout>
</session-config>
(10)mime-mapping
<mime-mapping>
<extension>htm</extension>
<mime-type>text/html</mime-type>
</mime-mapping>
(11)welcome-file-list欢迎文件页
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
(12)error-page错误页面
<!-- 1、通过错误码来配置error-page。当系统发生×××错误时,跳转到错误处理页面。 -->
<error-page>
<error-code>404</error-code>
<location>/NotFound.jsp</location>
</error-page>
<!-- 2、通过异常的类型配置error-page。当系统发生java.lang.NullException(即空指针异常)时,跳转到错误处理页面。 -->
<error-page>
<exception-type>java.lang.NullException</exception-type>
<location>/error.jsp</location>
</error-page>
(13)jsp-config设置jsp
<jsp-config> 包括 <taglib> 和 <jsp-property-group> 两个子元素。其中<taglib> 元素在JSP 1.2 时就已经存在;而<jsp-property-group> 是JSP 2.0 新增的元素。
<jsp-property-group> 元素主要有八个子元素,它们分别为:
<description>:设定的说明
<display-name>:设定名称
<url-pattern>:设定值所影响的范围,如: /CH2 或 /*.jsp
<el-ignored>:若为 true,表示不支持 EL 语法
<scripting-invalid>:若为 true,表示不支持 <% scripting %>语法
<page-encoding>:设定 JSP 网页的编码
<include-prelude>:设置 JSP 网页的抬头,扩展名为 .jspf
<include-coda>:设置 JSP 网页的结尾,扩展名为 .jspf
<jsp-config>
<taglib>
<taglib-uri>Taglib</taglib-uri>
<taglib-location>/WEB-INF/tlds/MyTaglib.tld</taglib-location>
</taglib>
<jsp-property-group>
<description>Special property group for JSP Configuration JSP example.</description>
<display-name>JSPConfiguration</display-name>
<url-pattern>/jsp/* </url-pattern>
<el-ignored>true</el-ignored>
<page-encoding>GB2312</page-encoding>
<scripting-invalid>true</scripting-invalid>
<include-prelude>/include/prelude.jspf</include-prelude>
<include-coda>/include/coda.jspf</include-coda>
</jsp-property-group>
</jsp-config>
对于Web 应用程式来说,Scriptlet 是个不乐意被见到的东西,因为它会使得HTML 与Java 程式码交相混杂,对于程式的维护来说相当的麻烦,必要的时候,可以在web.xml 中加上 标签,设定所有的JSP 网页都不可以使用Scriptlet。
web.xml(本项目)
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>Archetype Created Web Application</display-name>
<!--<context-param>-->
<!-- <param-name>log4jConfigLocation</param-name>-->
<!-- <param-value>classpath:log4j.properties</param-value>-->
<!--</context-param>-->
<listener>
<listener-class>
org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<!--加载spring容器-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
<url-pattern>*.js</url-pattern>
<url-pattern>*.html</url-pattern>
<url-pattern>*.jpg</url-pattern>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--配置springMVC的编码过滤器-->
<filter>
<filter-name>CharacterEncodingFilter</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>-->
<!--<init-param>-->
<!-- <param-name>fileEncoding</param-name>-->
<!-- <param-value>UTF-8</param-value>-->
<!--</init-param>-->
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--将 POST 请求转换为 DELETE 或 PUT 请求-->
<!--必须先注册CharacterEncodingFilter,再注册HiddenHttpMethodFilter-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>HttpPutFormContentFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpPutFormContentFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 设置session失效时间 -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<!--配置404页面-->
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/page/error/404.html</location>
</error-page>
</web-app>
3、Mapping规则
当一个请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url,比如我访问的是http://localhost/test/aaa.html,我的应用上下文是test,容器会将http://localhost/test去掉,剩下的/aaa.html部分拿来做servlet的映射匹配。这个映射匹配过程是有顺序的,而且当有一个servlet匹配成功以后,就不会去理会剩下的servlet了。
其匹配规则和顺序如下:
精确路径匹配。例子:比如servletA 的url-pattern为 /test,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test ,这个时候容器就会先 进行精确路径匹配,发现/test正好被servletA精确匹配,那么就去调用servletA,也不会去理会其他的servlet了。
最长路径匹配。例子:servletA的url-pattern为/test/,而servletB的url-pattern为/test/a/,此时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB。
扩展匹配,如果url最后一段包含扩展,容器将会根据扩展选择合适的servlet。例子:servletA的url-pattern:.action
以”/’开头和以”/”结尾的是用来做路径映射的。以前缀”.”开头的是用来做扩展映射的。所以,为什么定义”/.action”这样一个看起来很正常的匹配会错?因为这个匹配即属于路径映射,也属于扩展映射,导致容器无法判断。