尚筹网Java项目实战开发教程

项目架构

在这里插入图片描述

技术要求

Spring,MyBatis,SpringMVC,Maven:根据任务去分析实现任务功能的思路,然后根据思路去画出流程图步骤,在把流程图步骤翻译成注解,在根据注解去编写代码

总结:目标 > 思路 > 代码

创建工程

在这里插入图片描述

MyBatis逆向工程

MyBatis的逆向工程会去根据数据表自动生成pojo类、dao接口、sql映射文件。也就是说,逆向工程的目的是为了简化开发,加快我们的开发步骤。

配置逆向工程的依赖

<!--导入Mybatis核心依赖-->
<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>
</dependencies>
<!-- 控制Maven 在构建过程中相关配置-->
<build>
    <!-- 构建过程中用到的插件-->
    <plugins>
        <!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的-->
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.0</version>
            <!-- 插件的依赖-->
            <dependencies>
                <!-- 逆向工程的核心依赖-->
                <dependency>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-core</artifactId>
                    <version>1.3.2</version>
                </dependency>
                <!-- 数据库连接池-->
                <dependency>
                    <groupId>com.mchange</groupId>
                    <artifactId>c3p0</artifactId>
                    <version>0.9.2</version>
                </dependency>
                    <!-- MySQL 驱动-->
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.8</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>
<?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>
    <!-- mybatis-generator:generate -->
    <context id="atguiguTables" targetRuntime="MyBatis3">
        <commentGenerator>
            <!-- 是否去除自动生成的注释true:是;false:否-->
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!--数据库连接的信息:驱动类、连接地址、用户名、密码-->
        <jdbcConnection
                driverClass="com.mysql.jdbc.Driver"
                connectionURL="jdbc:mysql://localhost:3306/project_crowd"
                userId="root"
                password="123456">
        </jdbcConnection>

        <!-- 默认false,把JDBC DECIMAL 和NUMERIC 类型解析为Integer,为true 时把JDBC DECIMAL和NUMERIC 类型解析为java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- targetProject:生成Entity 类的路径-->
        <javaModelGenerator targetProject=".\src\main\java"  targetPackage="com.atguigu.crowd.entity">
            <!-- enableSubPackages:是否让schema 作为包的后缀-->
            <property name="enableSubPackages" value="false" />
            <!-- 从数据库返回的值被清理前后的空格-->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!-- targetProject:XxxMapper.xml 映射文件生成的路径-->
        <sqlMapGenerator targetProject=".\src\main\java" targetPackage="com.atguigu.crowd.mapper">
            <!-- enableSubPackages:是否让schema 作为包的后缀-->
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>

        <!-- targetPackage:Mapper 接口生成的位置-->
        <javaClientGenerator type="XMLMAPPER" targetProject=".\src\main\java" targetPackage="com.atguigu.crowd.mapper">
            <!-- enableSubPackages:是否让schema 作为包的后缀-->
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>
        <!-- 数据库表名字和我们的entity 类对应的映射指定-->
        <table tableName="t_admin" domainObjectName="Admin" />
    </context>
</generatorConfiguration>

执行逆向生成操作的Maven 命令

mybatis-generator:generate

把生成的文件放置对应的层

配置父工程的依赖管理

<?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.atguigu.crowd</groupId>
    <artifactId>atcrowdfunding01-admin-parent</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>atcrowdfunding02-admin-webui</module>
        <module>atcrowdfunding03-admin-component</module>
        <module>atcrowdfunding04-admin-entity</module>
        <module>atcrowdfunding05-common-util</module>
        <module>atcrowdfunding06-common-reverse</module>
    </modules>
	
	<!--统一管理版本号-->
    <properties>
        <!-- 声明属性,对Spring 的版本进行统一管理-->
        <atguigu.spring.version>4.3.20.RELEASE</atguigu.spring.version>
        <!-- 声明属性,对SpringSecurity 的版本进行统一管理-->
        <atguigu.spring.security.version>4.2.10.RELEASE</atguigu.spring.security.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- Spring 依赖-->
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
                <version>${atguigu.spring.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${atguigu.spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>${atguigu.spring.version}</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.2</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/cglib/cglib -->
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>2.2</version>
            </dependency>
            <!-- 数据库依赖-->
            <!-- MySQL 驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.3</version>
            </dependency>
            <!-- 数据源-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.0.31</version>
            </dependency>
            <!-- MyBatis -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.2.8</version>
            </dependency>
            <!-- MyBatis 与Spring 整合-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>1.2.2</version>
            </dependency>
            <!-- MyBatis 分页插件-->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper</artifactId>
                <version>4.0.0</version>
            </dependency>
            <!-- 日志-->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>1.7.7</version>
            </dependency>
            <dependency>
                <groupId>ch.qos.logback</groupId>
                <artifactId>logback-classic</artifactId>
                <version>1.2.3</version>
            </dependency>
            <!-- 其他日志框架的中间转换包-->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>jcl-over-slf4j</artifactId>
                <version>1.7.25</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>jul-to-slf4j</artifactId>
                <version>1.7.25</version>
            </dependency>
            <!-- Spring 进行JSON 数据转换依赖-->
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-core</artifactId>
                <version>2.9.8</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.9.8</version>
            </dependency>
            <!--JSON解析器-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.5</version>
            </dependency>
            <!-- JSTL 标签库-->
            <dependency>
                <groupId>jstl</groupId>
                <artifactId>jstl</artifactId>
                <version>1.2</version>
            </dependency>
            <!-- junit 测试-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
            <!-- 引入Servlet 容器中相关依赖-->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>2.5</version>
                <scope>provided</scope>
            </dependency>
            <!-- JSP 页面使用的依赖-->
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>jsp-api</artifactId>
                <version>2.1.3-b06</version>
                <scope>provided</scope>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>2.8.5</version>
            </dependency>
            <!-- SpringSecurity 对Web 应用进行权限管理-->
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-web</artifactId>
                <version>4.2.10.RELEASE</version>
            </dependency>
            <!-- SpringSecurity 配置-->
            <dependency>
            <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-config</artifactId>
                <version>4.2.10.RELEASE</version>
            </dependency>
                <!-- SpringSecurity 标签库-->
                <dependency>
                    <groupId>org.springframework.security</groupId>
                    <artifactId>spring-security-taglibs</artifactId>
                    <version>4.2.10.RELEASE</version>
                </dependency>
        </dependencies>
    </dependencyManagement>
</project>

依赖信息来源

到专门网站搜索:https://mvnrepository.com
调试:根据实际运行情况,确认jar 包之间是否兼容

Spring和Mybatis整合

思路:
在这里插入图片描述

  • 导入依赖
  • 准备jdbc.properties配置文件
  • 创建Spring和MyBatis的整合配置文件
  • 在整合配置文件加载jdbc文件
  • 配置数据源,如C3P0,Druid
  • 配置sqlSessionFactory,装配数据源,配置一些MyBatis操作
  • 配置MapperScannerConfigurer,去扫描Mapper接口

导入依赖

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/cglib/cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
        </dependency>
        <!-- MySQL 驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>
        <!-- MyBatis 与Spring 整合-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
        </dependency>
        <!-- MyBatis 分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
        </dependency>
        <!--JSON解析器-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.5</version>
        </dependency>
        <!-- JSTL 标签库-->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>

准备jdbc.properties配置文件

jdbc.driverClassName=com.mysql.jdbc.Driver
#useUnicode=true&characterencoding=UTF-8 指定字符的编码、解码格式
jdbc.url=jdbc:mysql://localhost:3306/project_crowd?useUnicode=true&characterEncoding=UTF-8
jdbc.user=root
jdbc.password=123456

配置整合

<?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"
       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/aop
			    http://www.springframework.org/schema/aop/spring-aop.xsd
			    http://www.springframework.org/schema/tx
			    http://www.springframework.org/schema/tx/spring-tx.xsd
			    http://www.springframework.org/schema/mvc
			    http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--加载外部文件-->
    <context:property-placeholder location="classpath*:*.properties"/>

    <!--配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <!--驱动程序-->
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <!--地址-->
        <property name="url" value="${jdbc.url}"/>
        <!--用户名-->
        <property name="username" value="${jdbc.user}"/>
        <!--密码-->
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--配置sqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--装配数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!--加载MyBatis的全局文件,里面有一些MyBatis配置-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--加载Mapper的文件-->
        <property name="mapperLocations" value="classpath*:mybatis/mapper/*.xml"/>
    </bean>

    <!--配置MapperScannerConfigurer来扫描Mapper接口所在的包-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.atguigu.crowd.mapper"/>
    </bean>
</beans>

日志系统

能给我提供程序运行的信息和错误,方便我们根据信息去调试程序
在这里插入图片描述

logback 配置文件

logback 工作时的具体细节可以通过logback.xml 来配置

<?xml version="1.0" encoding="UTF-8" ?>
<configuration debug="true">
    <!-- 指定日志输出的位置-->
    <appender name="STDOUT"
              class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日志输出的格式-->
            <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体
            内容、换行-->
            <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
        </encoder>
    </appender>
    <!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR -->
    <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。-->
    <root level="INFO">
        <!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
        <appender-ref ref="STDOUT" />
    </root>
    <!-- 根据特殊需求指定局部日志级别-->
    <logger name="com.atguigu.crowd.mapper" level="DEBUG"/>
</configuration>

声明式事务

从事务角度: 一个事务方法中包含的多个数据库操作,要么一起提交、要么一起回滚。也就是说事务方法中的多个数据库操作,有任何一个失败,整个事务全部回滚。

从声明式角度: 交由Spring 来全面接管数据库事务。用声明式代替编程式

	try {
		// 核心操作前:开启事务(关闭自动提交)
		// 对应AOP 的前置通知
		connection.setAutoCommit(false);
		// 核心操作
		adminService.updateXxx(xxx, xxx);
		// 核心操作成功:提交事务
		// 对应AOP 的返回通知
		connection.commit();
	}catch(Exception e){
		// 核心操作失败:回滚事务
		// 对应AOP 的异常通知
		connection.rollBack();
	}finally{
		// 不论成功还是失败,核心操作终归是结束了
		// 核心操作不管是怎么结束的,都需要释放数据库连接
		// 对应AOP 的后置通知
		if(connection != null){
			connection.close();
		}
	}

就是将以上操作交由Spring来操作

添加AOP依赖:

<!-- AOP 所需依赖-->
<dependency>
	<groupId>org.aspectj</groupId>
	<artifactId>aspectjweaver</artifactId>
</dependency>
<!-- AOP 所需依赖-->
<dependency>
	<groupId>cglib</groupId>
	<artifactId>cglib</artifactId>
</dependency>

思路:

在这里插入图片描述

<?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"
       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/aop
			    http://www.springframework.org/schema/aop/spring-aop.xsd
			    http://www.springframework.org/schema/tx
			    http://www.springframework.org/schema/tx/spring-tx.xsd
			    http://www.springframework.org/schema/mvc
			    http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--配置自动扫描包-->
    <context:component-scan base-package="com.atguigu.crowd.service"/>

    <!--创建事务管理器,注入数据源-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--虽然跟数据源不在一个文件里面,它是去Spring容器里加载数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--配置事务属性-->
        <tx:attributes>
            <!--查询方法,使用read-only="true"属性配置查询方法为只读,让数据库知道这是个查询方法,然后可以对他进行优化-->
            <!--查询的一些方法名字定义-->
            <tx:method name="get*" read-only="true"/>
            <tx:method name="find*" read-only="true"/>
            <tx:method name="query*" read-only="true"/>
            <tx:method name="count*" read-only="true"/>

            <!--增删改方法,给他们配置事务传播行为和回滚异常-->
            <!--
                propagation:事务传播行为
                    REQUIRED:默认值,表示当前方法必须工作在事务中,如果当前没有开启事务,则会开启新事务,如果有开启的事务,那么会去使用已有的事务
                    REQUIRES_NEW:表示当前方法必须工作在事务中,如果当前没有开启事务,则会开启新事务,就算有开启的事务,也要运行在自己的事务中
                rollback-for:在什么异常下回滚事务
                    默认:运行时异常
                    建议:运行时异常和编译时异常
            -->
            <tx:method name="save*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
            <tx:method name="update*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
            <tx:method name="remove*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
            <tx:method name="batch*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception"/>
        </tx:attributes>
    </tx:advice>

    <!--配置AOP-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="px" expression="execution(* *..*ServiceImpl.*(..))"/>
        <!--将事务通知与切入点关联-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="px"/>
    </aop:config>
</beans>
  • 创建DataSourceTransactionManager事务管理器,注入数据源
  • 配置事务通知,事务属性
  • 使用AOP对方法进行增强

注意:tx:method事务属性是必须配置的,一个tx:method对应这你要进行的事务方法,否则事务对这个方法不起作用

配置SpringMvc【表示层】

在这里插入图片描述

页面 > handler 【@RequestMapping】> Service > Mapper > 数据库

添加MVC依赖

 <!--SpringMVC依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
</dependency>

<!-- 引入Servlet 容器中相关依赖-->
<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>servlet-api</artifactId>
	<scope>provided</scope>
</dependency>

<!-- JSP 页面使用的依赖-->
<dependency>
	<groupId>javax.servlet.jsp</groupId>
	<artifactId>jsp-api</artifactId>
	<scope>provided</scope>
</dependency>

配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--配置加载Spring文件的监听器,并初始化Spring容器-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-persist-*.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--配置编码过滤器-->
    <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>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <!--配置强制响应编码-->
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <!--
        这个Filter要在所有Filter之前
        原因如下:
            他是使用的是request.setCharacterEncoding(encoding)来设置请求和响应编码的,
            他是要设置在获取请求参数request.getParameter()之前的和响应response.getWriter()之前的
    -->
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--配置Restful风格的URL 过滤器-->
    <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>

    <!--配置前端控制器-->
    <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:spring-web-mvc.xml</param-value>
        </init-param>
        <!--
            为什么要设置load-on-startup应为DispatcherServlet在创建后有大量的框架初始化的工作,不适合在第一次请求时来做
            所以使用load-on-startup把他设置为web启动时去创建和初始化工作
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <!--<url-pattern>/*</url-pattern>-->
        <!--
            请求配置方式2:配置请求扩展名
                缺点:不能使用RESTFul风格
                优点:
                    1.可以使静态资源不经过SpringMVC,可以不要特殊处理
                    2.可以实现伪静态效果,表面上看起来是一个访问静态资源的请求,但是实际上是由SpringMVC交给handler 来处理的动态资源
                        给黑客增加入侵
                        有利于SEO优化
        -->
        <url-pattern>*.html</url-pattern>
        <!--
            为什么要扩展json
            应为如果一个AJAX请求扩展是html,但是响应的是json格式,就会造成请求扩展名和响应体的数据格式不匹配,会出现406错误
        -->
        <url-pattern>*.json</url-pattern>
    </servlet-mapping>
</web-app>

配置MVC.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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/aop
			    http://www.springframework.org/schema/aop/spring-aop.xsd
			    http://www.springframework.org/schema/tx
			    http://www.springframework.org/schema/tx/spring-tx.xsd
			    http://www.springframework.org/schema/mvc
			    http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--配置自动扫描包,扫描handler-->
    <context:component-scan base-package="com.atguigu.crowd.mvc"/>

    <!--配置注解驱动-->
    <mvc:annotation-driven/>

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前置-->
        <property name="prefix" value="/WEB-INF/"/>
        <!--后置-->
        <property name="suffix" value=".jsp"/>
    </bean>
    .......
</beans>

SSM整合测试

index.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <a href="${pageContext.request.contextPath}/test/ssm.html">测试SSM整合环境</a>
</body>
</html>

target.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${requestScope.admin}
</body>
</html>

创建Controller类

package com.atguigu.crowd.mvc.Controller;

import com.atguigu.crowd.entity.Admin;
import com.atguigu.crowd.service.api.AdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@Controller
public class TestHandler {
    @Autowired
    private AdminService adminService;

    @RequestMapping("/test/ssm.html")
    public String testSsm(Model model){
      List<Admin> admins=adminService.getAll();
      model.addAttribute("admin",admins);
      return "target";
    }
}

getAll方法

/**
 * 查询
 * @return
 */
public List<Admin> getAll() {
    //selectByExample()根据Example条件进行查询
    return adminMapper.selectByExample(new AdminExample());
}

测试结果
在这里插入图片描述

使用Base配置通用url

将页面上路径中的${pageContext.request.contextPath}部分提取到页面开头

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%--http://localhost:9090/test/ssm.html--%>
    <base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}"/>
</head>
<body>
    <a href="test/ssm.html">测试SSM整合环境</a>
</body>
</html>

SpringMVC 环境下的Ajax 请求

前端发送过来,后端要处理的请求有两种:

  • 普通请求:后端处理完成后返回页面,浏览器使用使用页面替换整个窗口中的内容

    请求 > handler处理 > 页面

  • Ajax 请求:后端处理完成后通常返回JSON 数据,jQuery 代码使用JSON 数据对页面局部更

    ajax > handler处理 > json

常用注解

@ResponseBody和@RequestBody,使用它们要添加json依赖如:fastjson

<!--JSON解析器-->
<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.5</version>
</dependency>

流程:

在这里插入图片描述

@ResponseBody注解

@responseBody注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据。

注意:在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据

package com.atguigu.crowd.mvc.Controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class TestHandler {

    @ResponseBody
    @RequestMapping("/test/json.html")
    public String getJson(){
        return "ResponseBody";
    }
}

在这里插入图片描述

@RequestBody注解

用于获取请求体的内容(注意:get方法不可以,因为get没有请求体),也可以使用@RequestBody注解把json的字符串转换成JavaBean的对象

@RequestBody 使用的场景:传统发送请求参数方式不方便发送的数据,使用JSON 请求体的方式发送。特别是要发送复杂对象的时候。

场景设定

jQuery 通过Ajax 请求给服务器端发送一个数组:[5,8,12]

加入jQuery
在这里插入图片描述


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%--http://localhost:9090/test/ssm.html--%>
    <base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}"/>
    <%--导入jquery--%>
    <script type="text/javascript" src="jquery/jquery-2.1.1.min.js"></script>

    <script type="text/javascript">
        $(function () {
            $("#btn").click(function () {
                //数组
                var array=[5,8,12];
                //传为json字符串
                var jsonArray = JSON.stringify(array);
                alert(jsonArray);
                //使用ajax异步发送
                $.ajax({
                    url: "send/array/three.html",//请求地址
                    type: "post",//请求方式
                    data: jsonArray,//请求体
                    contentType: "application/json;charset=UTF-8", // 告诉服务器端当前请求的请求体是JSON格式
                    dataType: "text",       //如何对待服务器返回的数据
                    success: function (response) { //服务器成功处理请求后调用的回调函数,response是响应体数据
                        alert(response);
                    },
                    error: function (response) { //服务器处理请求失败后的回调函数,response是响应体数据
                        alert("请求失败")
                    }
                });
            });
        })
    </script>
</head>
<body>
    <a href="test/ssm.html">测试SSM整合环境</a>

    <button id="btn">Send [5,8,12]</button>
</body>
</html>
package com.atguigu.crowd.mvc.Controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
public class TestHandler {
    @ResponseBody
    @RequestMapping("/send/array/three.html")
    public String getJson1(@RequestBody List<Integer> array){
        for (Integer arrays:array){
            System.out.println(arrays);
        }
        return "ok";
    }

}

在这里插入图片描述

AJAX发送复杂对象

映射实体类

/**
 * @author 强哥
 */
public class Student implements Serializable {
    /**
     * id
     */
    private Integer stuId;
    /**
     * 姓名
     */
    private String stuName;
    /**
     * 地址
     */
    private Address address;
    /**
     * 科目
     */
    private List<Subject> subject;

    private Map<String,String> map;
	.......
}


public class Address implements Serializable {
    /**
     * 省
     */
    private String province;
    /**
     * 市
     */
    private String city;
    /**
     * 街道
     */
    private String street;
    .....
}

public class Subject implements Serializable {
    /**
     * 科目
     */
    private String subjectName;
    /**
     * 成绩
     */
    private Integer subjectScore;
    .....
}

统一返回数据格式

package com.atguigu.crowd.util;

/**
 * 用于规范AJAX的返回,统一返回一个规范
 * @author 强哥
 * @param <T>
 */
public class ResultEntity<T> {
    /**
     * 返回成功的信息
     */
    private static final String SUCCESS="success";
    /**
     * 返回错误的信息
     */
    private static final String FAILED="failed";

    //状态码
    private String result;
    //请求处理失败时返回的错误的信息
    private String message;
    //要返回的数据
    private T data;

    /**
     * 请求处理成功且不返回数据的工具方法
     * @param <Type>
     * @return
     */
    public static <Type> ResultEntity<Type> successWithoutData(){
        return new ResultEntity<Type>(SUCCESS,null,null);
    }

    /**
     * 请求处理成功且需要返回数据的工具方法
     * @param <Type>
     * @return
     */
    public static <Type> ResultEntity<Type> successWithData(Type data){
        return new ResultEntity<Type>(SUCCESS,null,data);
    }

    /**
     * 请求处理失败的工具方法
     * @param message
     * @param <Type>
     * @return
     */
    public static <Type> ResultEntity<Type> failed(String message){
        return new ResultEntity<Type>(null,FAILED,null);
    }


    public ResultEntity() {
    }

    public ResultEntity(String result, String message, T data) {
        this.result = result;
        this.message = message;
        this.data = data;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "ResultEntity{" +
                "result='" + result + '\'' +
                ", message='" + message + '\'' +
                ", data=" + data +
                '}';
    }
}

ajax代码


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <%--http://localhost:9090/test/ssm.html--%>
    <base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}"/>
    <%--导入jquery--%>
    <script type="text/javascript" src="jquery/jquery-2.1.1.min.js"></script>

    <script type="text/javascript">
        $(function () {
        	//单击事件
            $("#btn1").click(function () {
                var student={
                	//id
                    "stuId":5,
                    //姓名
                    "stuName":"tom",
                    //地址
                    "address":{
                    	//省
                        "province":"广东",
                        //市
                        "city":"深圳",
                        //街道
                        "street":"后瑞"
                    },
                    //科目
                    "subject":[
                    	//科目名 成绩
                        {"subjectName":"javaSE","subjectScore":100},
                        {"subjectName":"SSM","subjectScore":90}
                    ],
                    "map":{
                        "k1":"v1",
                        "k2":"v2"
                    }
                };
                //就JSON对象转换为JSON字符串,方便对象的传输
                var stringify = JSON.stringify(student);
                //使用ajax异步发送
                $.ajax({
                    //请求地址
                    url:"send/compose/object.json",
                    //请求方式
                    type:"post",
                    //请求体
                    data:stringify,
                    //告诉服务器端当前请求的请求体是JSON格式
                    contentType:"application/json;charset=UTF-8",
                    //如何对待服务器返回的数据
                    dataType:"json",
                    //服务器成功处理请求后调用的回调函数,response是响应体数据
                    success:function (response) {
                       console.log(response)
                    },
                    //服务器处理请求失败后的回调函数,response是响应体数据
                    error:function (response) {
                        alert("请求失败")
                    }
                });
            });
        })
    </script>
</head>
<body>
    <button id="btn1">发送复杂对象</button>
</body>
</html>

Controller层

package com.atguigu.crowd.mvc.Controller;

import com.atguigu.crowd.entity.Admin;
import com.atguigu.crowd.entity.Student;
import com.atguigu.crowd.service.api.AdminService;
import com.atguigu.crowd.util.ResultEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


@Controller
public class TestHandler {
    @Autowired
    private AdminService adminService;

    /**
     * 使用指定类初始化日志对象,在日志输出的时候,可以打印出日志信息所在类
     */
    private Logger logger= LoggerFactory.getLogger(TestHandler.class);

    @ResponseBody
    @RequestMapping("/send/compose/object.json")
    public ResultEntity<Student> testReceiveComposeObject(@RequestBody Student student){
        //打印日志
        logger.info(student.toString());
        //使用返回统一数据格式工具类,返回信息
        return ResultEntity.successWithData(student);
    }
}

结果

前台
在这里插入图片描述
后台
在这里插入图片描述

异常映射

使用异常映射机制对整个项目的异常和错误显示进行统一管理

注意:SpringMVC提供了基于XML和注解的两种异常映射机制

基于XML异常映射

异常页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%--
        exception: 异常对象,当一个页面在运行中发生了异常,就会创建这个对象
        message:返回错误信息
    --%>
    <H1>出错了,${pageContext.exception.message}</H1>
</body>
</html>

在MVC配置中配置XML异常映射

<!--配置基于XML的异常映射-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <!--配置异常类型和具体视图的对应关系-->
    <property name="exceptionMappings">
        <props>
            <!--key:指定具体的异常全类名-->
            <!--标签体中编写对应的视图-->
            <prop key="java.lang.Exception">system-error</prop>
        </props>
    </property>
</bean>

Controller层

@Controller
public class TestHandler {
    @RequestMapping("/test/error.html")
    public String testError(){
    	//设置异常
        int i=10/0;
        return "target";
    }
}

结果:
在这里插入图片描述

基于注解异常映射

编写判断当前请求是否为Ajax 请求工具类,判断依据
在这里插入图片描述

package com.atguigu.crowd.util;

import javax.servlet.http.HttpServletRequest;

/**
 * 判断是普通请求还是ajax请求的工具类
 * @author 强哥
 */
public class CrowdUtil {
    /**
     * 判断是否是ajax请求
     * @param request
     * @return
     *      true 是Ajax请求
     *      false 不是Ajax请求
     */
    public static Boolean judgeRequestType(HttpServletRequest request){
        String accept = request.getHeader("Accept");
        String xRequested = request.getHeader("X-Requested-With");
        //contains:判断是否包含某个字符串
        return (accept!=null&&accept.contains(accept)) || (xRequested!=null&& "XMLHttpRequest".equals(xRequested));
    }

}

测试工具类

@Controller
public class TestHandler {
    @RequestMapping("/test/error.html")
    public String testError(HttpServletRequest request){
        boolean aBoolean = CrowdUtil.judgeRequestType(request);
        logger.info("什么请求:"+(aBoolean?"Ajax请求":"普通请求"));
        /*int i=10/0;*/
        return "target";
    }
}

在url中访/test/error.html

结果:
在这里插入图片描述
测试注解异常映射

package com.atguigu.crowd.mvc.config;

import com.alibaba.fastjson.JSON;
import com.atguigu.crowd.util.CrowdUtil;
import com.atguigu.crowd.util.ResultEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * ControllerAdvice:表示当前类是一个异常处理类
 * @author 强哥
 */
@ControllerAdvice
public class CrowdExceptionResolver {
    /**
     * ExceptionHandler:将一个具体的异常跟一个方法关联起来
     * @param request
     * @return
     */
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointerException(Exception exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        String viewName="system-error";
        return commonResolveException(viewName,exception,request,response);
    }

    /**
     * 公共方法
     * @param viewName 异常对应的页面
     * @param exception 异常类,通过它去获取异常信息
     * @param request   请求
     * @param response  响应
     * @return
     * @throws IOException
     */
    private ModelAndView commonResolveException(String viewName,Exception exception,HttpServletRequest request,HttpServletResponse response) throws IOException {
        ModelAndView modelAndView = new ModelAndView();
        //如果是Ajax请求
        if (CrowdUtil.judgeRequestType(request)){
            //ResultEntity使用工具类返回错误信息,使用error.getMessage()去获取错误信息
            ResultEntity<Object> failed = ResultEntity.failed(exception.getMessage());
            //传为json字符串
            String string = JSON.toJSONString(failed);
            //把当前JSON 字符串作为当前请求的响应体数据返回给浏览器
            response.getWriter().write(string);
            //返回null,不给SpringMVC 提供ModelAndView 对象
            //这样SpringMVC 就知道不需要框架解析视图来提供响应,而是程序员自己提供了响应
            return null;
        }
        //如果不是Ajax请求,将Exception对象存入模型
        modelAndView.addObject("error",exception);
        //设置视图显示错误信息
        modelAndView.setViewName(viewName);
        //返回modelAndView对象
        return modelAndView;
    }

}

结果: 当出现空指针异常时会调用CrowdExceptionResolver异常处理类的对应异常方法进行处理

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值