SSM超详细整合教程(附带shiro+log4j2框架的整合)及源码

Spring

       Spring是最受欢迎的企业级java应用程序开发框架,Spring最被人所认同的技术是控制反转的依赖注入(DI)模式。控制反转(Ioc)是一个通用的概念,它可以用许多种不同的方式去表达,而依赖注入仅仅是控制反转的一个具体的例子。除此之外Spring广为人知一个框架便是AOP,关于AOP的应用有很多不错的例子,如日志记录、声明性事务、安全性、和缓存等等。关于Spring的控制反转(Ioc)以及控制反转的依赖注入模式(DI)与Spring的关键组件面向方面的程序设计(AOP)框架这里就不做过多的阐述,有兴趣的小伙伴可以去看我关于Spring的专题。

SpringMVC

        SpringMVC框架是一个基于请求的驱动的web框架,并且使用了前端控制器的模型来进行设计,再根据映射规则分发给相应的页面控制器进行处理。

        整体流程如下:

         1.首先用户发送请求到前端控制器(DispatcherServlet),前端控制器根据请求信息(如URL)来决定选择哪一个页面控制器进行处理并把请求委托给它。图中的1、2步骤。

         2.页面控制器收到请求后,进行功能处理,首先需要收集和绑定请求参数到一个对象,这个对象在Spring Web MVC中叫命令对象,并进行验证,然后将命令对象委托给业务对象进行处理,处理完毕后返回一个ModelAndView(模型数据和逻辑图名),图中的3、4、5步骤。

         3.前端控制器收回控制权,然后根据返回的逻辑视图名选择相应的视图进行渲染,并把模型数据传入以便视图渲染。图中的6、7步骤。

         4.前端控制器再次收回控制权,将响应返回给用户,至此请求过程中后端请求过程结束,图中的8步骤。

         SpringMVC请求过程核心流程:

具体步骤:

第一步:发起请求到前端控制器(DispatcherServlet)

第二步:前端控制器请求处理器映射器(HandlerMapping)查找处理器(Handler)。注:可以根据xml配置、注解进行查找

第三步:处理器映射器(handlerMapping)向前端控制器返回处理器(Handler),HandlerMapping会把请求映射为HandlerExcutionChain对象(它包含一个Handler处理器(页面控制器)对象,多个HandlerInterceptor拦截器对象),通过这种策略模式,很容易添加新的映射策略。

第四步:前端控制器调用处理器适配器去执行Handler

第五步:处理器适配器(HandlerAdapter)将会根据适配的结果去执行Handler

第六步:Handler执行完成给适配器返回ModelAndView

第七步:处理器适配器向前端控制器返回ModelAndView(ModelAndView是SpringMvc框架的一个底层对象,包括Model和View)

第八步:前端控制器请求视图解析器去进行视图解析(根据逻辑视图名解析成真诚的视图(jsp)),通过这种策略很容易更换其他视图技术,只需要更改视图解析器即可。

第九步:视图解析器向前端控制器返回View

第十步:前端控制器进行视图渲染(视图渲染将模型数据(在ModelAndVies)填充到request域)

第十一步:前端控制器向用户响应结果。

 

核心开发步骤:

1.DispatcherServlet在web.xml中描述,从而拦截请求到Spring Web Mvc

2.HandlerMapping的配置,从而将请求映射到处理器

3.HandlerAdapter的配置,从而支持多种类型的处理器

注:处理器映射器和处理器适配器包含在注解驱动中,不需要再单独配置。

4.ViewResolver的配置,从而将逻辑视图名解析为具体视图技术

5.处理器(页面控制器)的配置,从而进行功能处理

View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf...)

Mybatis

      mybatis的前身是Apache的开源项目iBatis。mybatis几乎可以代替JDBC,是一个支持普通SQl查询、存储过程和高级映射的基于java的优秀持久层框架。mybatis与JDBC相比,减少了50%以上的代码量。并且满足高并发和高响应的要求,所以它称为最流行的java互联网持久框架。

      mybatis使用简单的XML或注解用于配置和原始映射,将接口和java的POJOs(Plain Old Java Objects,普通的java对象)映射成数据库中的记录  。关于mybatis的后续将会有相应的mybatis专栏,有兴趣的朋友可以前去指正一下。

SSM整合思路

在Spring中将各层进行整合

通过Spring管理持久层的mapper(相当于dao接口)

通过Spring管理业务层的service,service中可以调用mapper接口。

在Spring中进行事务控制

通过Spring管理表现层Controller,Controller中可以调用service接口。

mapper、service、Controller都是javabean,可以由Spring来进行统一管理。

基本思路:

第一步:整合dao

mybatis和spring整合,通过spring管理mapper接口。

使用mapper的扫描器自动扫描mapper接口在spring中进行注册。

第二步:整合service

通过Spring管理service接口。

使用配置方式将service接口配置在spring配置文件中。

实现事务控制。

第三步:整合springmvc

由于springmvc是spring的模块,不需要整合。

SSM整合

ssm使用图解

进行ssm三大框架整合之前先大概了解一下三大框架各自的作用,在整合思路里已经说过了,这里重新赘述一下,加深一下理解

1.SpringMVC:他用于web层,相当于Controller(等价于传统的servlet和struts的action),用来处理用户请求。举个例子用户在地址栏输入http://网站域名/login,那么springmvc就会拦截到这个请求,并且调用controller层中相应的方法(中间可能包含验证用户名密码和业务和逻辑,以及查询数据库操作,但这些都不是springmvc的职责),最终把结果返回给用户,并且返回相应的页面(当然也可以只返回json/xml等格式数据)。springmvc就是做前面和后面的活,与用户打交道。

2.Spring:关于spring与我们平常开发接触最多的就是IOC容器,他可以装载bean(也就是我们java中的类,当然也包括service      和dao里面的),有了这个机制我们就不用在每次使用这个类的时候为它初始化,很少看到关键字new。另外Spring的aop,事务管理等我们也是十分经常遇到。

3.MyBatis:如果你想问它跟那个大名鼎鼎的Hibernate有什么区别,我只能说mybatis更符合大多数人的需求。第一、他能自由控制sql,这会让有数据库经验的人编写的代码能够提高数据库访问的效率。第二、他可以使用xml的方式来组织管理sql,因为一般程序出错很多情况下是sql出错,别人接手代码后能够快速找到出错的地方,甚至可以优化原来写的sql。

第一步:创建maven工程

1.创建项目

2.选择maven——>Create from archetype——>选择如图模版

3.命名

这里着重说一下,GroupId是项目组织的唯一标识符,举个例子,如果你的公司名字叫做myself,有个项目叫做study,那么GroupId就应该是com.myself.study;而ArtifactedId则定义了当前项目在组中唯一的ID,比如study-ssm、study-shiro、study-redis等等。

填好了GroupId和ArtifactedId以后一直next,初次创建的时候生成比较慢,耐心等待就好了。生成项目如下:

第二步:创建目录

生成的项目只是很简单的项目结构,并不能满足我们的需求,所以我们要创建一些目录,如下:

目录介绍如下:

文件名作用
src根目录,下面有main
main主要目录,可以放java代码和一些资源文件。
java存放 Java 代码
comjava文件的子文件
myselfcom文件的子文件

equipment

区别于主程序的其他代码,如果没有,也可以不用创建
study存放主要的java代码

controller

存放我们程序的接口代码也就是控制器,springmvc就是在这里发挥作用的
dao数据访问层:与数据打交道,可以是数据库操作,也可以是文件读写操作,甚至是redis缓存操作,总之与数据操作有关的都放在这里,在这里我们只需要写接口就可以,不用实现dao接口的实现类impl,因为我们使用的持久层框架是mybatis,可以在mapper中的xml配置文件中直接实现接口的方法。
entity实体类:一般来说与数据库的表相对应,封装dao层取出来的数据为对象,一般只在dao层与service层传输。
service业务逻辑层:在此处一般来处理我们的业务逻辑,controller直接调用它,将控制器层与逻辑层分开,有利于解耦合。
resources存放资源文件,如spring,springmvc,mybatis,日志、数据库等的配置文件。
conf存放程序的配置文件,一般存放spring,mybatis,日志、数据库等
applicationContext.xmlSpring的配置文件

generator.properties

mybatis中的代码自动生成功能的属性文件
generatorConfig.xmlmybatis中的代码自动生成功能的配置文件
jdbc.properties配置数据库的相关参数
log4j2.xml配置日志的相关参数
springmvc.xml配置springmvc的配置文件
mapper存放dao中每个方法对应的sql,故而dao不需要写方法的实现(impl)
sqlsql文件中一般存放一些sql的脚本,比如数据库的表或者其他方面的改动。
systemsystem文件中可以放一些程序中用到的其他的properties文件,与conf中的properties文件区分开来,便于调用。
webapp存放前端的静态资源,比如jsp,js,css等
resources这里的resources存放项目的静态资源,比如js,css,image等
css存放css
images存放iamge
js存放js文件
WEB-INF很重要的一个目录,外部浏览器无法访问,只有项目内部才能访问,可以把jsp放在这里,另外就是web.xml了。你可能有疑问了,为什么上面java中的resources里面的配置文件不妨在这里,那么是不是会被外部窃取到?你想太多了,打包部署时候基本上只有webapp里面的静态资源如js、image、css等会直接输出到根目录,其他都会放入WEB-INF里面,项目内部依然可以使用classpath:XXX来访问,IDE里可以设置部署输出目录
jsp存放jsp代码
web.xml一个重要的但非必须配置文件,web.xml是用来配置欢迎页、servlet、filter等的,当你的web工程没用到这些的时候,你可以不用web.xml文件来配置你的web工程。
index.jspjsp进入网站默认的首页,也可以通过web.xml的配置来更改首页的jsp
pom.xmlpom.xml是maven的配置文件,pom.xml主要描述了项目的maven坐标、依赖关系、开发者需要遵从的规则、组织和licenses、以及其他所有你的项目相关因素。是项目级别的配置文件。

接下来就进行ssm的整合,在整合的过程中同时整合了log4j2与shiro框架;

第三步:配置相关配置文件

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.myself.study</groupId>
    <artifactId>study-ssm</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>study-ssm Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <!-- 设置项目编码编码 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- spring版本号 -->
        <spring.version>5.2.2.RELEASE</spring.version>
        <spring.security.version>4.2.3.RELEASE</spring.security.version>
        <jstl.version>1.2</jstl.version>
        <servlet.version>4.0.1</servlet.version>
    </properties>

    <dependencies>
        <!--spring的三个核心依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!--两个主要的页面依赖-->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <!--log4j2的三个依赖包-->
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.11.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-web -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-web</artifactId>
            <version>2.11.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-jcl -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-jcl</artifactId>
            <version>2.11.2</version>
        </dependency>

        <!--json数据处理依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.62</version>
        </dependency>
        <!--mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.4</version>
        </dependency>
        <!--mybatis整合spring依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>
        <!--连接池-->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.2.RELEASE</version>
        </dependency>

        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
        </dependency>

        <!--shiro的三个依赖包 -->
        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.5.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-web -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.5.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.5.2</version>
        </dependency>

        <!-- lombomk-->
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
            <scope>provided</scope>
        </dependency>

        <!--Jackson 是当前用的比较广泛的,用来序列化和反序列化 json 的 Java 的开源框架,Spring MVC 的默认 json 解析器便是 Jackson,如果不引入该包在前台进行请求的时候
        就会报错,因为后台无法解析发送的json数据-->
        <!--
        jackson-core,核心包,提供基于"流模式"解析的相关 API,它包括 JsonPaser 和 JsonGenerator。 Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json。
        jackson-annotations,注解包,提供标准注解功能;
        jackson-databind ,数据绑定包, 提供基于"对象绑定" 解析的相关 API ( ObjectMapper ) 和"树模型" 解析的相关 API (JsonNode);基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API。-->
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.10.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.10.1</version>
        </dependency>

    </dependencies>
    <build>
        <finalName>studyssm</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>
        </resources>

        <!--mybatis-generator插件-->
        <!--<plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>
                <configuration>
                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
                <executions>
                    <execution>
                        <id>Generate MyBatis Artifacts</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.2</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>-->
    </build>
</project>

applicationContext.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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       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.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <!--开启注解模式-->
    <!--使用context:annotation-config/ 就可以隐式地自动向Spring容器注册4个BeanPostProcessor:
    AutowiredAnnotationBeanPostProcessor
    CommonAnnotationBeanPostProcessor
    PersistenceAnnotationBeanPostProcessor
    RequiredAnnotationBeanPostProcessor
    这样就可以使用@ Resource 、@ PostConstruct、@ PreDestroy、@PersistenceContext、@Autowired、@Required等注解了,就可以实现自动注入。
    注册这4个 BeanPostProcessor的作用,就是为了你的系统能够识别相应的注解。
    -->
    <context:annotation-config/>


    <!--自动扫描除了Controller以外的注解-->
    <context:component-scan base-package="com.myself.study">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>


    <!--数据库连接池-->
    <!--加载配置文件-->
    <context:property-placeholder  location="classpath:conf/jdbc.properties"/>
    <!-- 配置数据源 -->
    <bean id="dataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="123456"/>
    </bean>

    <!-- 配置mybatis的sqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!-- 自动扫描mappers.xml文件 -->
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
        <!-- mybatis配置文件 -->
        <property name="configLocation" value="classpath:conf/mybatis-config.xml"/>
    </bean>

    <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.myself.study.dao" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <!-- 配置自定义Realm -->
    <bean id="myRealm" class="com.myself.study.service.realm.myRealm"/>
    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="myRealm"/>
    </bean>
    <!-- Shiro过滤器 核心-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- Shiro的核心安全接口,这个属性是必须的 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 身份认证失败,则跳转到登录页面的配置 -->
        <property name="loginUrl" value="/login.jsp"/>
        <!-- 权限认证失败,则跳转到指定页面 -->
        <property name="unauthorizedUrl" value="/login.jsp"/>
        <!-- Shiro连接约束配置,即过滤链的定义 -->
        <property name="filterChainDefinitions">
            <value>
                <!--anon 表示匿名访问,不需要认证以及授权-->
                /loginAdmin=anon
                <!--authc表示需要认证 没有进行身份认证是不能进行访问的-->
                /admin*=authc
                /student=roles[teacher]
                /teacher=perms["user:create"]
            </value>
        </property>
    </bean>
    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    <!-- 开启Shiro注解 -->
    <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
          depends-on="lifecycleBeanPostProcessor"/>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>
</beans>

spring-mvc.xml

<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-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

<!--     注解的映射器  -->
    <!--      <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> -->
    <!--     注解的适配器 -->
    <!--      <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> -->
    <!-- 使用 mvc:annotation-driven可以代替上面注解映射器和注解适配器配置
    mvc:annotation-driven默认加载了很多的参数绑定方法,比如json转换解析器就默认加载了
    实际开发中使用mvc:annotation-driven
    -->
    <!-- 注解驱动:配置处理器映射器和适配器 -->
    <mvc:annotation-driven/>
    <!--springmvc容器中指定扫描controller注解,并且指定相应的包-->
    <context:component-scan base-package="com.myself.study.controller">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    

    <!-- 视图解析器
    解析jsp解析,默认使用jstl标签,classpath下得有jstl的包
    -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--使用JSTL标签, 则指定InternalResourceViewResolver的viewClass属性为org.springframework.web.servlet.view.JstlView.-->
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <!-- 如果配置的有html视图解析器,则viewClass的值则配置为如下所示 -->
        <!--   <property name="viewClass" value="org.springframework.web.servlet.view.InternalResourceView"/>  -->
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/"/>
        <!-- 后缀 -->
        <property name="suffix" value=".jsp"/>
        <property name="contentType" value="text/html;charset=UTF-8"/>
        <!--配置优先等级,值越小等级越高-->
        <property name="order" value="0"/>
    </bean>
    <!--静态资源映射-->
    <mvc:resources mapping="/css/**" location="/resources/css/"/>
    <mvc:resources mapping="/js/**" location="/resources/js"/>

</beans>

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"/>
    </settings>
<!-- 扫描entity包,使用别名 -->
<typeAliases>
    <package name="com.myself.study.entity"/>
</typeAliases>
<!-- 映射map -->
<mappers/>
</configuration>

jdbc.properties

driver=com.mysql.jdbc.Driver
#mytest为我本地的数据库名
url=jdbc:mysql://localhost:3306/ssm?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=UTF-8
username=root
#下面输入自己数据库的密码
password=123456
#定义初始连接数
initialSize=0
#定义最大连接数
maxActive=20
#定义最大空闲
maxIdle=20
#定义最小空闲
minIdle=1
#定义最长等待时间
maxWait=60000

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--status="WARN" :用于设置log4j2自身内部日志的信息输出级别,默认是OFF-->
<!--monitorInterval="30"  :间隔秒数,自动检测配置文件的变更和重新配置本身-->
<configuration status="WARN" monitorInterval="0">
    <Properties>
        <!--自定义一些常量,之后使用${变量名}引用-->
        <Property name="logFilePath">/Users/danghongen/temporary/log</Property>
        <Property name="logFileName">test.log</Property>
    </Properties>
    <!--appenders:定义输出内容,输出格式,输出方式,日志保存策略等,常用其下三种标签[console,File,RollingFile]-->
    <appenders>
        <!--console :控制台输出的配置-->
        <console name="Console" target="SYSTEM_OUT">
            <!--PatternLayout :输出日志的格式,LOG4J2定义了输出代码,详见第二部分-->
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
        </console>
        <!--File :同步输出日志到本地文件-->
        <!--append="false" :根据其下日志策略,每次清空文件重新输入日志,可用于测试-->
        <File name="log" fileName="${logFilePath}/${logFileName}" append="false">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
        </File>
        <!--SMTP :邮件发送日志-->
        <!--<SMTP name="Mail" subject="****SaaS系统正式版异常信息" to="message@message.info" from="message@lengjing.info" smtpUsername="message@message.info" smtpPassword="LENG****1234" smtpHost="mail.lengjing.info" smtpDebug="false" smtpPort="25" bufferSize="10">
            <PatternLayout pattern="[%-5p]:%d{YYYY-MM-dd HH:mm:ss} [%t] %c{1}:%L - %msg%n" />
        </SMTP>-->
        <!-- ${sys:user.home} :项目路径 -->
        <RollingFile name="RollingFileInfo" fileName="${logFilePath}/logs/info.log"
                     filePattern="${logFilePath}/logs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
            <!--ThresholdFilter :日志输出过滤-->
            <!--level="info" :日志级别,onMatch="ACCEPT" :级别在info之上则接受,onMismatch="DENY" :级别在info之下则拒绝-->
            <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <!-- Policies :日志滚动策略-->
            <Policies>
                <!-- TimeBasedTriggeringPolicy :时间滚动策略,默认0点小时产生新的文件,interval="6" : 自定义文件滚动时间间隔,每隔6小时产生新文件, modulate="true" : 产生文件是否以0点偏移时间,即6点,12点,18点,0点-->
                <TimeBasedTriggeringPolicy interval="6" modulate="true"/>
                <!-- SizeBasedTriggeringPolicy :文件大小滚动策略-->
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
            <!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>

        <RollingFile name="RollingFileWarn" fileName="${logFilePath}/logs/warn.log"
                     filePattern="${logFilePath}/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>
        <RollingFile name="RollingFileError" fileName="${logFilePath}/logs/error.log"
                     filePattern="${logFilePath}/logs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
            <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
            <PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
        </RollingFile>
    </appenders>
    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <!--Logger节点用来单独指定日志的形式,name为包路径,比如要为org.springframework包下所有日志指定为INFO级别等。 -->
        <!--<logger name="org.springframework" level="INFO"></logger>
        <logger name="org.mybatis" level="INFO"></logger>-->
        <!-- Root节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出 -->
        <root level="all">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileInfo"/>
            <appender-ref ref="RollingFileWarn"/>
            <appender-ref ref="RollingFileError"/>
        </root>
        <!--AsyncLogger :异步日志,LOG4J有三种日志模式,全异步日志,混合模式,同步日志,性能从高到底,线程越多效率越高,也可以避免日志卡死线程情况发生-->
        <!--additivity="false" : additivity设置事件是否在root logger输出,为了避免重复输出,可以在Logger 标签下设置additivity为”false”-->
        <!--<AsyncLogger name="AsyncLogger" level="trace" includeLocation="true" additivity="false">
            <appender-ref ref="RollingFileError"/>
        </AsyncLogger>-->
    </loggers>
</configuration>

generator.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8
username=root
password=123456

#entity 包名和 java目录
modelPackage=com.myself.study.entity
modelProject=src/main/java
#sqlmap包名 和resources目录
sqlPackage=mapper
sqlProject=src/main/resources
#mapper包名和 java目录
mapperPackage=com.myself.study.dao
mapperProject=src/main/java

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>
    <!--导入属性配置 -->
    <properties resource="generator.properties"/>

    <classPathEntry
            location="/Users/danghongen/develop/maven/repository/mysql/mysql-connector-java/5.1.41/mysql-connector-java-5.1.41.jar" />
    <context id="context1">
        <!-- 注释 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" /><!-- 是否取消注释 -->
            <property name="suppressDate" value="true" /> <!-- 是否生成注释代时间戳 -->
        </commentGenerator>

        <jdbcConnection driverClass="${driver}"
                        connectionURL="${url}"
                        userId="${username}"
                        password="${password}" />
        <!-- 类型转换 -->
        <javaTypeResolver>
            <!-- 是否使用bigDecimal, false可自动转化以下类型(Long, Integer, Short, etc.) -->
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!--生成entity的包名和位置-->
        <javaModelGenerator targetPackage="${modelPackage}" targetProject="${modelProject}">
            <!-- 在targetPackage的基础上,根据数据库的schema再生成一层package,最终生成的类放在这个package下,默认为false -->
            <property name="enableSubPackages" value="false"/>
            <!-- 设置是否在getter方法中,对String类型字段调用trim()方法-->
            <property name="trimStrings" value="false"/>
        </javaModelGenerator>
        <!--生成映射文件的包名和位置-->
        <sqlMapGenerator targetPackage="${sqlPackage}" targetProject="${sqlProject}">
            <!-- 在targetPackage的基础上,根据数据库的schema再生成一层package,最终生成的类放在这个package下,默认为false -->
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>
        <!--生成mapper(也可叫做dao)的包名和位置-->
        <javaClientGenerator targetPackage="${mapperPackage}" targetProject="${mapperProject}" type="XMLMAPPER">
            <!-- 在targetPackage的基础上,根据数据库的schema再生成一层package,最终生成的类放在这个package下,默认为false -->
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>

        <!--要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名,如果需要通配所有表 直接用sql的通配符    %即可 -->
        <table schema="" tableName="%" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>

    </context>
</generatorConfiguration>

web.xml:

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="3.0"

         xmlns="http://java.sun.com/xml/ns/javaee"

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd_0.xsd">
  <display-name>studySSM</display-name>

  <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
      <!-- 该值缺省为false,表示声明周期由SpringApplicationContext管理,设置为true表示ServletContainer管理 -->
      <param-name>targetFilterLifecycle</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <!--log4j文件配置-->
  <context-param>
    <param-name>log4jConfiguration</param-name>
    <!--默认是classpath下的log4j2.xml-->
    <param-value>classpath:conf/log4j2.xml</param-value>
  </context-param>
  <!--log4j的监听器要放在Spring监听器前面-->
  <listener>
    <listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class>
  </listener>
  

  <!-- 启动Spring 配置spring容器相关的资源文件和创建容器的监听-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:conf/applicationContext.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <listener>
    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
  </listener>



  <!-- 配置springmvc的前端控制器 指向spring-mvc.xml 程序在启动的时候就加载springmvc 可以接受所有请求 load-on-startup:表示启动容器时初始化该Servlet; -->
  <servlet>
    <servlet-name>springMvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 可以自定义servlet.xml配置文件的位置和名称, 默认为WEB-INF目录下,名称为[<servlet-name>]-servlet.xml,如spring-servlet.xml -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value> classpath:conf/spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <!-- 将前端URL请求和后台处理方法controller建立对应关系-->
  <servlet-mapping>
    <servlet-name>springMvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

关于ssm与shiro整合主要是realm的重写,重写的realm名字为myRealm类,该类需要继承AuthorizingRealm并重写doGetAuthorizationInfo()方法与doGetAuthenticationInfo()方法;如下所示:

myRealm.java

package com.myself.study.service.realm;

import com.myself.study.entity.SysUser;
import com.myself.study.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Arrays;

public class myRealm extends AuthorizingRealm {

//  注解Resource与Autowired类似但不相同
    @Autowired
    UserService userService;

    /**
     * 为当前登录成功的用户授予权限和角色,已经登录成功了
     */

    /*参数解释:
    * PrincipalCollection:是一个身份集合,而方法getPrimaryPrincipal则是得到主要的身份,需要注意的是,如果只有一个Principal则直接返回,如果有多个,则返回第一个(因为内部使用map储存,所以可以认为是返回任意一个)
    * SimpleAuthorizationInfo:用于聚合授权信息
    * */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username=(String) principalCollection.getPrimaryPrincipal();//获取用户名
        SimpleAuthorizationInfo authenticationInfo=new SimpleAuthorizationInfo();
        authenticationInfo.setRoles(userService.getRoles(username));//set角色字符串信息
        authenticationInfo.setStringPermissions(userService.getPermissions(username));//set权限字符串信息
        return authenticationInfo;
    }


    /**
     * 验证当前登陆的用户,获取认证信息
     */
    /*参数解释:
    * AuthenticationToken:AuthenticationToken 用于收集用户提交的身份(如用户名)及凭据(如密码)
    *AuthenticationInfo:AuthenticationInfo对象中存储的是主体(Subject)的身份认证信息。Shiro会调用CredentialsMatcher对象的doCredentialsMatch方法
                        对AuthenticationInfo对象和AuthenticationToken进行匹配。匹配成功则表示主体(Subject)认证成功,否则表示认证失败。。
 *在认证成功以后进行权限与角色的查询,需要创建SimpleAuthenticationInfo对象。
 * SimpleAuthenticationInfo:SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
userInfo, //用户名–此处传的是用户对象
userInfo.getPassword(), //密码—从数据库中获取的密码
salt,//盐–用于加密密码对比,–获取的经验:为了防止两用户的初始密码是一样的,
       四个参数,防止两用户可能初始密码相同时候用,token 用simplehash(四个参数的构造) 加密默认用了MD5 迭代一次加密,
       info中在密码比对调用new SimpleHash(String algorithmName, Object source)这个实例化对象默认迭代一次了,
       所以当你用三个参数加密时候可能两 个初始密码相同人的就没能区别开 (因此realm中密码要从数据库的查的原因),通过设置reaml 中credentialsMatcher 属性的各项属性可实现
getName() //当前的realm名
); */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
        String username=token.getUsername();//获取用户名
        String password= Arrays.toString(token.getPassword());
        SysUser user=userService.getByUsername(username);
        if (user!=null){
            if (!password.equals(user.getPassword())){
                return new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),"myRealm");
            }else {
                throw new AccountException("密码错误!");
            }

        }else {
            throw new AccountException("账号不存在");
        }
    }
}

以上是我整合完成后的配置文件,在整合的过程中还遇到过很多问题,我专门写了一篇问题集锦,以及相应的源码地址以及数据库的sql文件!

文章地址如下:https://blog.csdn.net/weixin_40159122/article/details/105507947

源码地址如下(附带数据库的SQL文件):https://github.com/danghongen/study-ssm

想学习的童鞋一定要自己手动搭建一遍,遇到问题可以留言给我!

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值