由于尚硅谷的视频是通过Eclipse软件来做的,其中有些操作与IDEA上有所区别,所以我在这里将IDEA区别于Eclipse的操作、操作过程中涉及的源码(与视频的源码略有出入)以及大家可能遇到的种种问题分享给大家,这些源码在我这里均是通过测试的,仅供参考!
1 IDEA版本
使用Ultimate版本,Community版创建不了maven project
2 构建Project以及各Module
2.1 Packaging
IDEA在建立Maven Module中并没有对Packaging的设置,可以在建立Module后在pom.xml中进行定义:
<packaging>war</packaging>
<packaging>jar</packaging>
2.2 webui(war打包类型)的框架支持
需要在创建之后添加web框架支持,右击Module文件夹:
选择Web Application:
2.3 Dependencies建立
在需要添加依赖的pom文档中Alt+Ins,选择Dependency,具体依赖关系参照工程文档
2.4 Dependencies可视化查看
Maven project窗口中有直接查看Diagram的图标,也可在pom文档中邮件Diagrams中查看
3 建立数据库表
将SQL语句直接复制到SQLyog运行即可
CREATE DATABASE `project_crowd` CHARACTER SET utf8;
USE project_crowd;
DROP TABLE IF EXISTS t_admin;
CREATE TABLE t_admin
(
id INT NOT NULL AUTO_INCREMENT, # 主键
login_acct VARCHAR(255) NOT NULL, # 登录账号
user_pswd CHAR(32) NOT NULL, # 登录密码
user_name VARCHAR(255) NOT NULL, # 昵称
email VARCHAR(255) NOT NULL, # 邮件地址
create_time CHAR(19), # 创建时间
PRIMARY KEY (id)
);
4 基于Maven的MyBatis逆向工程
4.1 Mybatis依赖
将mybatis的依赖添加至reverse的pom文档中
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
</dependencies>
如果仍未下载mybatis,则直接在maven project中选择Reload,即可自动下载
<build>
<!--构建过程中用到的插件-->
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<configurationFile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<!--插件的依赖-->
<dependencies>
<!--逆向工程核心依赖-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
4.2 generatorConfig配置及源代码修改
在reverse-src-main-resouces中新建generatorConfig.xml,注意:
- 数据库连接信息填写本地数据库的userId以及password!
- 工程文档中connectionURL中并没有在后缀中添加 ‘&serverTimezone=UTC‘ 字段,如果不添加会导致系统提示时区值无法识别或包含多个时区(SQLyog 5.7)
<?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.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/project_crowd&serverTimezone=UTC"
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>
4.3 逆向生成操作
IDEA中可以直接在Maven project窗口中进行操作,在reverse-Plugins找到刚创建的mybatis-generator,右击构建即可:
已知问题在4.2提出过,修改后运行结果如下:
4.4 在生成的类中添加构造方法
Alt + insert
4.5 将生成的类及xml放入个module中
可能会出现的问题:
- 转移文件时import相对路径指向修改
- component module需要在pom文件中添加对mybatis依赖
转移后IDEA project结构如下图:
5 父工程依赖管理
<properties>
<!-- 声明属性, 对 Spring 的版本进行统一管理 -->
<!-- spring.version是别名,随便起,但要跟dependences标签中一致 -->
<spring.version>5.2.11.RELEASE</spring.version>
<!-- 声明属性, 对 SpringSecurity 的版本进行统一管理 -->
<spring.security.version>5.4.2</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>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
<!-- 数据库依赖 -->
<!-- MySQL 驱动 -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- 数据源 -->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.3</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!-- MyBatis 与 Spring 整合 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.5</version>
</dependency>
<!-- MyBatis 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
<!-- 日志 -->
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.0-alpha1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.3.0-alpha5</version>
<scope>test</scope>
</dependency>
<!-- 其他日志框架的中间转换包 -->
<!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>2.0.0-alpha1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/jul-to-slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>2.0.0-alpha1</version>
</dependency>
<!-- Spring 进行 JSON 数据转换依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.3</version>
</dependency>
<!-- JSTL 标签库 -->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- junit 测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- 引入 Servlet 容器中相关依赖 -->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- JSP 页面使用的依赖 -->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</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.6</version>
</dependency>
<!-- SpringSecurity 对 Web 应用进行权限管理 -->
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.4.2</version>
</dependency>
<!-- SpringSecurity 配置 -->
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.4.2</version>
</dependency>
<!-- SpringSecurity 标签库 -->
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-taglibs -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>5.4.2</version>
</dependency>
</dependencies>
</dependencyManagement>
6 Spring与MyBatis聚合
6.1 子工程依赖添加
添加至Component的pom文件中,工程文档中对JSTL标签库的依赖无法识别,进行了简要修改
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>com.atguigu.crowd</groupId>
<artifactId>atcrowdfunding04-admin-entity</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.atguigu.crowd</groupId>
<artifactId>atcrowdfunding05-common-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- Spring 依赖 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
<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>
<!-- Spring 进行 JSON 数据转换依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- JSTL 标签库 -->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
</dependencies>
6.2 数据库连接信息
在webui-src-main-resources中新建jdbc.properties文件,注意username和password填写按照本地数据库账号填写
另外url上需要指定时区,之前提到过,不然会死循环,在工程文档上有所改动
jdbc.url=jdbc:mysql://localhost:3306/project_crowd?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
jdbc.username=root
jdbc.password=123456
jdbc.driver=com.mysql.cj.jdbc.Driver
6.3 MyBatis配置文件
在webui-src-main-resources-mybatis中新建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>
</configuration>
6.4 spring-mybatis整合文件
在webui-src-main-resources中新建spring-persist-mybatis.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 加载 jdbc.properties -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!-- 连接数据库的用户名 -->
<property name="username" value="${jdbc.username}"/>
<!-- 连接数据库的密码 -->
<property name="password" value="${jdbc.password}"/>
<!-- 目标数据库的 URL 地址 -->
<property name="url" value="${jdbc.url}"/>
<!-- 数据库驱动全类名 -->
<property name="driverClassName" value="${jdbc.driver}"/>
</bean>
</beans>
6.5 测试类前的依赖添加
在老师对整合后的测试环节中,需要提前在webui的pom文件中添加junit和spring-test依赖,以免在后续引用注解时出现错误,这个视频里提到了但是文档里没提出
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
6.6 测试类
在webui-src-test-java-com.atguigu.crowd.test中新建Crowdtest.java
package com.atguigu.crowd.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
// 指定 Spring 给 Junit 提供的运行器类
@RunWith(SpringJUnit4ClassRunner.class)
// 加载 Spring 配置文件的注解
@ContextConfiguration(locations = {"classpath:spring-persist-mybatis.xml"})
public class CrowdTest {
@Autowired
private DataSource dataSource;
@Test
public void testDataSource() throws SQLException {
// 1.通过数据源对象获取数据源连接
Connection connection = dataSource.getConnection();
// 2.打印数据库连接
System.out.println(connection);
}
}
出现类似结果即为成功:
6.7 SqlSessionFactoryBean及MapperScannerConfigurer配置
在webui-src-main-resources的spring-persist-mybatis.xml文件中添加:
注意:视频中mybatis-config.xml更换了位置,所以路径也需要相应更改下
<!--配置SqlSessionFactoryBean整合MyBatis-->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--指定mybatis全局配置文件位置-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--指定mapper配置文件位置-->
<property name="mapperLocations" value="classpath:mybatis/mapper/*Mapper.xml"/>
<!--装配数据源:引用前面的dataSource数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置 MapperScannerConfigurer -->
<!-- 把 MyBatis 创建的 Mapper 接口类型的代理对象扫描到 IOC 容器中 -->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 使用 basePackage 属性指定 Mapper 接口所在包 -->
<property name="basePackage" value="com.atguigu.crowd.mapper"/>
</bean>
6.8 测试类
在webui-src-test-java-com.atguigu.crowd.test.Crowdtest.java继续添加新测试函数
@Autowired
private AdminMapper adminMapper;
@Test
public void testInsertAdmin(){
Admin admin;
admin = new Admin(null,"Tom","123123","汤姆","tom@qq.com",null);
int count = adminMapper.insert(admin);
System.out.println("受影响的行数" + count);
}
这里曾经出现报错,错误一大串,主要关心caused by那行(也就是最长的那行,翻到最后)
发现是AdminMapper.xml输出的文件相对路径搞错了,具体因为之前做的时候觉得文件前缀太长就略去了,后续导致AdminMapper里面提到的路径与实际文件路径不同所以报错。
修改后测试成功
7 日志系统
7.1 替换Spring的JCL方案
在webui-pom.xml中添加依赖
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
打印结果如下:
7.2 更换框架日志系统
- 如果使用spring5框架,不需要进行排除commons-logging的操作,只有spring4需要
- 在webui-pom.xml中添加依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
打印结果如下:
7.3 logback配置文件
在webui-src-main-resources新建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>
打印结果如下:
8 声明式事务
8.1 依赖添加
在webui-pom.xml中添加依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</dependency>
8.2 spring-persist-tx配置文件
在webui-src-main-resources新建spring-persist-tx.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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
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">
<!--配置自动扫描的包:主要是为了把Service扫描到IOC容器中-->
<context:component-scan base-package="com.atguigu.crowd.service"/>
<!--配置事务管理器-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--装配数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置AOP-->
<aop:config>
<!--配置切入点表达式-->
<aop:pointcut id="txPointcut" expression="execution(* *..*ServiceImpl.*(..))"/>
<!--将事务通知和切入点表达式关联到一起-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
<!--配置事务通知-->
<!-- id 属性用于在 aop:advisor 中引用事务通知 -->
<!-- transaction-manager 属性用于引用事务管理器,如果事务管理器的 bean 的 id 正好是 transactionManager,可以省略这个属性 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- name 属性指定当前要配置的事务方法的方法名 -->
<!-- 查询的方法通常设置为只读,便于数据库根据只读属性进行相关性能优化 -->
<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 表示:当前方法必须运行在事务中,如果没有事务,则开启事务,在自己的事务中运行。和 REQUIRED 的区别是就算现在已经有了已开启的事务, 也一定要开启自己的事务,避免和其他方法共用同一个事务。 -->
<!-- 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>
</beans>
8.3 测试类
在webui-src-test-java-com.atguigu.crowd.test.Crowdtest.java继续添加新测试函数
@Autowired
private AdminService adminService;
@Test
public void testTx(){
Admin admin = new Admin(null, "Jerry", "123456", "杰瑞", "jerry@qq.com", null);
adminService.saveAdmin(admin);
}
另外前面的扫描文件的注解新添加spring-persist-tx.xml
@ContextConfiguration(locations = {"classpath:spring-persist-mybatis.xml", "classpath:spring-persist-tx.xml"})
视频中将logback.xml中将指定日志级别由INFO级别改为了DEBUG级别,以获取更详细的打印日志
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
</root>
8.4 注意事项
视频中提到,但工程文档中没写:在基于xml的声明式事务中,事务属性的tx:method是必须配置的,如果某个方法没有配置对应的tx:method,那么事务对这个方法就不生效!
9 表述层
9.1 web配置文件
2.2中已经添加过web框架,按照视频转移到webui-src-main中
<?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">
<!-- 配置 ContextLoaderListener 加载 Spring 配置文件 -->
<!-- needed for ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-persist-*.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置 CharacterEncodingFilter 解决 POST 请求的字符乱码问题 -->
<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.setCharacterEncoding(encoding)必须在response.getWriter()前面-->
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置 SpringMVC 的前端控制器 -->
<!-- The front controller of this Spring Web application, responsible for handling all application
requests -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 以初始化参数的形式指定 SpringMVC 配置文件的位置 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-web-mvc.xml</param-value>
</init-param>
<!-- Servlet默认生命周期中,创建对象是在第一次接收到请求时 -->
<!-- 而DispatcherServlet创建对象后有大量的“框架初始化”工作,不合适在第一次请求时来做 -->
<!-- 设置load-on-startup就是为了让DispatcherServlet在Web应用启动时创建对象、初始化 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<!-- url-pattern配置方式一:表示拦截所有请求 -->
<!-- <url-pattern>/</url-pattern> -->
<!-- url-pattern配置方式二:配置请求扩展名 -->
<!-- 优点1:xxx.css、xxx.js、xxx.png等等静态资源完全不经过SpringMVC,不需要特殊处理 -->
<!-- 优点2:可以实现伪静态效果,表面上看起来是访问一个HTML的静态资源,但是实际上是经过Java代码运算的结果 -->
<!-- 伪静态作用1:给黑客入侵增加难度-->
<!-- 伪静态作用2:有利于SEO优化(让百度、谷歌这样的搜索引擎更容易找到我们的项目) -->
<!-- 缺点:不符合RESTFul风格 -->
<url-pattern>*.html</url-pattern>
<!-- 为什么要另外再配置json扩展名呢?-->
<!-- 如果一个Ajax请求扩展名是html,但是实际服务器给浏览器返回的是json数据,二者不匹配会出现406错误 -->
<!-- 为了让Ajax请求能够顺利拿下JSON格式的响应数据,我们另外配置json扩展名 -->
<url-pattern>*.json</url-pattern>
</servlet-mapping>
</web-app>
注意:在位置更新后可能会出现报错:“CharacterEncodingFilter” filter should have a mapping,需要进入file-projectstructure,重新添加web.xml可解决
9.2 spring-web-mvc配置文件
在webui-src-main-resources新建spring-web-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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 配置自动扫描的包:扫描handler -->
<context:component-scan base-package="com.atguigu.crowd.mvc"/>
<!-- 配置springmvc注解驱动 -->
<mvc:annotation-driven/>
<!-- 配置视图解析器 -->
<!-- 拼接公式→前缀+逻辑视图+后缀=物理视图 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀:附加到逻辑视图名称前 -->
<property name="prefix" value="/WEB-INF/"/>
<!-- 后缀:附加到逻辑视图名称后 -->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
9.3 依赖添加
在webui-pom.xml中添加依赖
<!-- 引入 Servlet 容器中相关依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- JSP 页面使用的依赖 -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<scope>provided</scope>
</dependency>
9.4 测试类
在webui-src-main-webapp新建index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>测试页面</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/test/ssm.html">测试SSM整合环境</a>
</body>
</html>
在component-src-main-java-com.atguigu.crowd-handler新建TestHandler.java
package com.atguigu.crowd.mvc.handler;
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.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
public class TestHandler {
@Autowired
private AdminService adminService;
@RequestMapping("/test/ssm.html")
public String testSSM(ModelMap modelMap){
List<Admin> adminList = adminService.getAll();
modelMap.addAttribute("adminList",adminList);
return "target";
}
}
其中getAll()方法没有定义,下面用快捷键快速构造方法:
-
IDEA中新建方法——Alt+Shift+Enter
-
IDEA中从接口找到实现类——Ctrl+Alt+B
-
IDEA在实现类快速添加方法——Ctrl+I
之后再AdminServiceImpl.java中编写一下getAll()方法:
@Override
public List<Admin> getAll() {
return adminMapper.selectByExample(new AdminExample());
}
在webui-src-main-webapp-WEB-INF新建target.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>AdminList</title>
</head>
<body>
<h1>Success</h1>
${requestScope.adminList}
</body>
</html>
Tomcat尚未配置的查一下网上其他攻略,这里就不说了,运行结果如下:
注意:如果在Tomcat的Output无法输出日志,如显示“No SLF4J providers were found”,请检查parent类和webui的日志依赖是否重复导入,将webui的依赖删除只保留parent即可。
9.5 base标签
将base标签修改为动态显示
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>测试页面</title>
<base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/"/>
</head>
<body>
<a href="test/ssm.html">测试SSM整合环境</a>
</body>
</html>
运行结果与9.5相同。
10 Ajax请求
10.1 jQuery.js文件放置
从网上下载jQuery.js,并放置到webui-src-main-webapp-js中
10.2 发送数组(一)
修改webui-src-main-webapp-index.jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>测试页面</title>
<base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/"/>
<script type="text/javascript" src="jquery/jquery-3.6.0.js"></script>
<script type="text/javascript">
$(function(){
$("#btn1").click(function(){
$.ajax({
"url": "send/array1.html", //请求目标资源的地址
"type": "post", //请求方式
"data": {
"array":[5,8,12] //要发送的请求参数
},
"dataType": "text", //如何对待服务器端返回的数据
"success": function (response){ //服务器端成功处理请求后调用的回调函数,response是响应体数据
alert(response);
},
"error": function (response){ //服务器端处理请求失败后调用的回调函数,response是响应体数据
alert(response);
}
});
});
})
</script>
</head>
<body>
<a href="test/ssm.html">测试SSM整合环境</a>
<br/>
<button id="btn1">Send [5,8,12]</button>
</body>
</html>
在component-src-main-java-com.atguigu.crowd-handler-TestHandler.java新增测试项
@ResponseBody
@RequestMapping("/send/array1.html")
public String testReceiveArrayOne(@RequestParam("array[]") List<Integer> array){
// 接收参数时需要在参数名后面加[]
for (Integer number : array){
System.out.println(number);
}
return "success";
}
测试结果如下:
10.3 发送数组(二)
这个test演示是失败的,就不贴代码了
10.4 发送数组(三)
修改webui-src-main-webapp-index.jsp文件
<script type="text/javascript">
$(function(){
$("#btn3").click(function(){
// 准备要发送的数组
var array = [5,8,12];
// 将JSON数组转换为JSON字符串
var requestBody = JSON.stringify(array);
$.ajax({
"url": "send/array3.html", //请求目标资源的地址
"type": "post", //请求方式
"data": requestBody,
"contentType":"application/json;charset=UTF-8",// 设置请求体的内容类型,告诉服务器端本次请求的请求体是JSON 格式
"dataType": "text", //如何对待服务器端返回的数据
"success": function (response){ //服务器端成功处理请求后调用的回调函数,response是响应体数据
alert(response);
},
"error": function (response){ //服务器端处理请求失败后调用的回调函数,response是响应体数据
alert(response);
}
});
});
})
</script>
在component-src-main-java-com.atguigu.crowd-handler-TestHandler.java新增测试项
@ResponseBody
@RequestMapping("/send/array3.html")
public String testReceiveArrayThree(@RequestBody List<Integer> array){
Logger logger = LoggerFactory.getLogger(TestHandler.class);
for (Integer number : array){
logger.info("number="+number);
}
return "success";
}
测试结果如下:
10.5 发送复杂对象
在entity-src-main-java-com.atguigu.crowd.entity中新建Student、Address、Subject类,这边只列举了声明对象,后面构造方法以及toString()自行添加
Student:
package com.atguigu.crowd.entity;
import java.util.List;
import java.util.Map;
public class Student {
private Integer stuId;
private String stuName;
private Address address;
private List<Subject> subjectList;
private Map<String,String> map;
}
Address:
package com.atguigu.crowd.entity;
public class Address {
private String province;
private String city;
private String street;
}
Subject:
package com.atguigu.crowd.entity;
public class Subject {
private String subName;
private Integer subScore;
}
修改webui-src-main-webapp-index.jsp文件
<script type="text/javascript">
$(function(){
$("#btn4").click(function (){
// 准备要发送的数据
var student = {
stuId: 5,
stuNmae: "tom",
address: {
province: "广东",
city: "深圳",
street: "街道"
},
subjectList: [
{
subName: "javase",
subScore: 100
},
{
subName: "SSM",
subScore: 99
}
],
map:{
key1: "v1",
key2: "v2"
}
};
// 将JSON对象转换为JSON字符串
var requestBody = JSON.stringify(student);
// 发送Ajax请求
$.ajax({
url: "send/compose/object.html",
type: "post",
data: requestBody,
contentType: "application/json;character=UTF-8",
dataType: "text",
success: function (response){
alert(response);
},
error: function (response) {
alert(response)
}
})
})
})
在component-src-main-java-com.atguigu.crowd-handler-TestHandler.java新增测试项
@ResponseBody
@RequestMapping("/send/compose/object.html")
public String testReceiveComplicatedObject(@RequestBody Student student){
logger.info(student.toString());
return "success";
}
测试结果:
10.6 ResultEntity
在util-src-main-java-com.atguigu.crowd-util新建ResultEntity.java
package com.atguigu.crowd.util;
public class ResultEntity<T> {
public static final String SUCCESS = "SUCCESS";
public static final String FAILED = "FAILED";
// 用来封装当前请求处理的结果是成功还是失败
private String result;
// 请求处理失败时返回的错误消息
private String message;
// 要返回的数据
private T data;
public ResultEntity(String success, Object o, Object o1) {
}
/*
* 请求处理成功且不需要返回数据时使用的工具方法
* @return
*/
public static <Type> ResultEntity<Type> successWithoutData(){
return new ResultEntity<Type>(SUCCESS, null, null);
}
/*
* 请求处理成功且需要返回数据时使用的工具方法
* @param data 要返回的数据
* @return
*/
public static <Type> ResultEntity<Type> successWithData(Type data){
return new ResultEntity<Type>(SUCCESS, null, data);
}
/*
* 请求处理失败后使用的工具方法
* @param message 失败的错误消息
* @return
*/
public static <Type> ResultEntity<Type> failed(String message) {
return new ResultEntity<Type>(FAILED, message, null);
}
public ResultEntity(String result, String message, T data){
super();
this.result = result;
this.message = message;
this.data = data;
}
@Override
public String toString() {
return "ResultEntity{" +
"result='" + result + '\'' +
", message='" + message + '\'' +
", data=" + data +
'}';
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}
修改webui-src-main-webapp-index.jsp文件
<script type="text/javascript">
$.ajax({
url: "send/compose/object.html",
type: "post",
data: requestBody,
contentType: "application/json;character=UTF-8",
dataType: "json",
success: function (response){
console.log(response)
},
error: function (response) {
console.log(response)
}
})
在component-src-main-java-com.atguigu.crowd-handler-TestHandler.java修改测试项
@ResponseBody
@RequestMapping("/send/compose/object.html")
public ResultEntity<Student> testReceiveComplicatedObject(@RequestBody Student student){
logger.info(student.toString());
return ResultEntity.successWithData(student);
}
测试结果:
11 异常映射
11.1 基于XML的异常映射
修改webui-src-main-resources-spring-web-mvc.xml文件
<!--配置基于XML的异常映射-->
<bean id="simpleMappingExceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 配置异常类型和具体视图页面对应关系 -->
<property name="exceptionMappings">
<props>
<!-- key属性指定异常全类名 标签体中写对应的视图(这个值要拼前后缀得到具体路径) -->
<prop key="java.lang.Exception">system-error</prop>
</props>
</property>
</bean>
在webui-src-main-webapp-WEB-INF新建system-error.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>出错了!</title>
</head>
<body>
<h1>出错了!</h1>
<!-- 从请求域取出Exception对象,再进一步访问message属性就能够显示错误消息 -->
${ requestScope.exception.message }
</body>
</html>
并在TestHandler中添加一个异常语句:
System.out.println(10 / 0);
测试结果:
11.2 判断请求类型的工具方法
在util的pom.xml中添加servlet依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
在util-src-main-java-com.atguigu.crowd-util新建CrowdUtil.java
public class CrowdUtil {
/*
* 判断当前请求是否为Ajax请求
* @param request 请求对象
* @return
* true:当前请求为Ajax请求
* false:当前请求不是Ajax请求
*/
public static boolean judgeRequestType(HttpServletRequest request) {
// 1. 获取请求头
String acceptHeader = request.getHeader("Accept");
String xRequestHeader = request.getHeader("X-Request-With");
// 2. 判断
return (acceptHeader != null && acceptHeader.contains("application/json"))
||
(xRequestHeader != null && xRequestHeader.equals("XMLHttpRequest"));
}
}
在component-src-main-java-com.atguigu.crowd-handler-TestHandler.java修改测试项
@ResponseBody
@RequestMapping("/send/compose/object.json")
public ResultEntity<Student> testReceiveComplicatedObject(@RequestBody Student student, HttpServletRequest request){
boolean judgeResult = CrowdUtil.judgeRequestType(request);
logger.info("judgeResult = "+judgeResult);
logger.info(student.toString());
return ResultEntity.successWithData(student);
}
@RequestMapping("/test/ssm.html")
public String testSSM(ModelMap modelMap, HttpServletRequest request){
boolean judgeResult = CrowdUtil.judgeRequestType(request);
logger.info("judgeResult = "+judgeResult);
List<Admin> adminList = adminService.getAll();
modelMap.addAttribute("adminList",adminList);
return "target";
}
输出结果,在进入ssm.html后显示:
在进入btn4后显示
11.3 基于注解的异常映射
在component-src-main-java-com.atguigu.crowd-mvc-config新建CrowdExceptionResolver.java,这里只列举空指针异常及构造的通用异常处理方法
package com.atguigu.crowd.mvc.config;
import com.atguigu.crowd.util.CrowdUtil;
import com.atguigu.crowd.util.ResultEntity;
import com.google.gson.Gson;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
// @ControllerAdvice表示当前类是一个基于注解的异常处理类
@ControllerAdvice
public class CrowdExceptionResolver {
// @ExceptionHandler将一个具体的异常类型和一个方法关联起来
@ExceptionHandler(value = NullPointerException.class)
public ModelAndView resolveNullPointerException(
//实际捕获到的异常类型
NullPointerException exception,
//当前请求对象
HttpServletRequest request,
//当前响应对象
HttpServletResponse response) throws IOException {
String viewName = "system-error";
return commonResolveException(viewName,exception,request,response);
}
// 创建通用方法
private ModelAndView commonResolveException(String viewName,
Exception exception,
HttpServletRequest request,
HttpServletResponse response ) throws IOException {
// 1. 判断当前请求类型
boolean judgeResult = CrowdUtil.judgeRequestType(request);
// 2. 如果为Ajax请求
if (judgeResult) {
// 3. 创建 ResultEntity 对象
ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());
// 4. 创建Gson对象
Gson gson = new Gson();
// 5. 将ResultEntity对象转换为JSON字符串
String json = gson.toJson(resultEntity);
// 6. 将JSON字符作为响应体返回给浏览器
response.getWriter().write(json);
// 7. 上面已经通过原生response对象返回了响应,因此不再提供ModelAndView对象
return null;
}
// 8. 如果不是Ajax请求,则创建ModelAndView对象
ModelAndView modelAndView = new ModelAndView();
// 9. 将Exception对象存入模型
modelAndView.addObject("exception", exception);
// 10. 设置对应的视图名称
modelAndView.setViewName(viewName);
// 11. 返回modelAndView对象
return modelAndView;
}
}
在util-src-main-java-com.atguigu.crowd-constant新建CrowdConstant.java
package com.atguigu.crowd.constant;
public class CrowdConstant {
public static final String MESSAGE_LOGIN_FAILED = "抱歉!账号密码错误,请重新输入!";
public static final String MESSAGE_LOGIN_ACCT_ALREADY_IN_USE = "抱歉!这个账号已经被使用了!";
public static final String MESSAGE_ACCESS_FORBIDDEN = "请登录以后再访问!";
public static final String ATTR_NAME_EXCEPTION = "exception";
}
12 管理员登录界面
12.1 admin-login界面
将admin-login源代码复制过来:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="keys" content="">
<meta name="author" content="">
<base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
<link rel="stylesheet" href="css/login.css">
<script src="jquery/jquery-3.6.0.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<style>
</style>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<div><a class="navbar-brand" href="index.html" style="font-size:32px;">尚筹网-创意产品众筹平台</a></div>
</div>
</div>
</nav>
<div class="container">
<form class="form-signin" role="form">
<h2 class="form-signin-heading"><i class="glyphicon glyphicon-log-in"></i> 管理员登录</h2>
<div class="form-group has-success has-feedback">
<input type="text" class="form-control" id="inputSuccess4" placeholder="请输入登录账号" autofocus>
<span class="glyphicon glyphicon-user form-control-feedback"></span>
</div>
<div class="form-group has-success has-feedback">
<input type="text" class="form-control" id="inputSuccess5" placeholder="请输入登录密码" style="margin-top:10px;">
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<button type="submit" class="btn btn-lg btn-success btn-block">登录</button>
</form>
</div>
</body>
</html>
修改webui-src-main-resources-spring-web-mvc.xml文件
<!--配置view-controller,直接把请求地址和视图名称关联起来,从而无需写handler方法-->
<mvc:view-controller path="/admin/to/login.html" view-name="admin-login"/>
进行测试:打开Tomcat后,在config中设置的url上后加/admin/to/login.html即可访问网址:
12.2 Layer
在index.jsp中引入layer
<script type="text/javascript" src="layer/layer.js"></script>
head中添加
$(function(){
$("#btn5").click(function (){
layer.msg("Layer的弹框");
})
});
body中添加
<br/>
<button id="btn5">点我弹框</button>
测试结果:
如果没有layer响应,建议reload maven或者重启下IDEA
12.3 System-error页面更新
更新system-error.jsp的页面
<!DOCTYPE html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="keys" content="">
<meta name="author" content="">
<base href="http://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
<link rel="stylesheet" href="css/login.css">
<script src="jquery/jquery-3.6.0.js"></script>
<script src="bootstrap/js/bootstrap.js"></script>
<script type="text/javascript">
$(function (){
$("button").click(function (){
// 相当于浏览器的后退按钮
window.history.back();
});
});
</script>
<style>
</style>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<div><a class="navbar-brand" href="index.html" style="font-size:32px;">尚筹网-创意产品众筹平台</a></div>
</div>
</div>
</nav>
<div class="container">
<h2 class="form-signin-heading" style="text-align: center;">
<i class="glyphicon glyphicon-log-in"></i>尚筹网系统消息
</h2>
<!--
requestScope对应的是存放request域数据的Map
requestScope.exception相当于request.getAttribute("exception")
requestScope.exception.message相当于exception.getMessage()
-->
<h3 style="text-align: center;"> ${ requestScope.exception.message } </h3>
<button style="width: 150px;margin: 50px auto 0px auto;" type="submit" class="btn btn-lg btn-success btn-block">点我返回上一步</button>
</div>
</body>
</html>
并在TestHandler.java中ssm.html的函数中增添bug测试页面
@RequestMapping("/test/ssm.html")
public String testSSM(ModelMap modelMap, HttpServletRequest request){
boolean judgeResult = CrowdUtil.judgeRequestType(request);
logger.info("judgeResult = "+judgeResult);
List<Admin> adminList = adminService.getAll();
modelMap.addAttribute("adminList",adminList);
System.out.println(10 / 0);
return "target";
}
测试结果如下: