虽然 springboot 自带的 hikaricp 连接池性能很好,个人更喜欢带有监控功能的 druid 连接池。
mybatis 的别名配置有点问题,在eclipse或IDEA中运行项目,别名能正常使用。将项目打成jar包后,别名就无法识别。
最近发现一片大佬写的文章,做个记录。https://blog.csdn.net/rainbow702/article/details/63255736
springboot版本 2.0.2.RELEASE
1. 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.hzj</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<druid.version>1.1.10</druid.version>
</properties>
<dependencies>
<!-- springboot springdata redis -->
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency> -->
<!-- spring html模板 thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- springboot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- log4j2 日志 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- mybatis-springboot starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- mysql connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Druid 数据连接池依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- Druid starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.6</version>
</dependency>
<!-- springboot test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- apache common -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
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.hzj</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<druid.version>1.1.10</druid.version>
</properties>
<dependencies>
<!-- springboot springdata redis -->
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency> -->
<!-- spring html模板 thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- springboot web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- log4j2 日志 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!-- mybatis-springboot starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- mysql connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Druid 数据连接池依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- Druid starter -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.6</version>
</dependency>
<!-- springboot test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- apache common -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.application.yml
#内嵌的 tomcat 的端口
server:
port: 8081
# 日志级别
logging:
level:
root: info
org.springframework: debug
mybatis:
# config-location: classpath:mybatis/mybatis-config.xml
#实体类所在包
type-aliases-package: com.hzj.demo.model
#mapper.xml所在位置
# mapper-locations: classpath:com/hzj/demo/mapper/read/*.xml
spring:
thymeleaf:
cache: false
prefix: classpath:/templates/
suffix: .html
encoding: UTF-8
mode: HTML5
#数据源配置 #Spring Boot 2.X 版本不再支持配置继承,多数据源的话每个数据源的所有配置都需要单独配置
datasource:
druid:
# Spring监控配置,说明请参考Druid Github Wiki,配置_Druid和Spring关联监控配置
aop-patterns: com.hzj.demo.*..*Service*.*(..),com.hzj.demo.*..*Mapper*.*(..)
# StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
stat-view-servlet:
enabled: true
url-pattern: /druid/*
reset-enable: true
login-username: hzj
login-password: 123456
allow: 127.0.0.1,localhost,192.168.1.208
# WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter
web-stat-filter:
enabled: true
profile-enable: true
exclusions: /druid/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico
session-stat-enable: true #session统计功能
filter:
stat:
db-type: mysql
log-slow-sql: true
slow-sql-millis: 2000
wall:
enabled: true
db-type: mysql
config:
delete-allow: false
drop-table-allow: false
#主数据配置
base:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
initialize: true #指定初始化数据源,是否用data.sql来初始化,默认: true
name: write
# url: jdbc:mysql://localhost:3306/test_write?useUnicode=true&characterEncoding=UTF8&useSSL=true #springboot 1.5.x 配置方式
url: jdbc:mysql://localhost:3306/test_write?useUnicode=true&characterEncoding=UTF8&useSSL=true #springboot 1.5.x 配置方式 #用 DruidDataSourceBuilder 时读取
# jdbc-url: jdbc:mysql://localhost:3306/test_write?useUnicode=true&characterEncoding=UTF8&useSSL=true #springboot 2.0.x 配置方式 #用spring的 DataSourceBuilder 的时候,读取
username: root
password: 123456
# 使用druid数据源
filters: stat,wall
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
connectionProperties: druid.stat.mergeSql=true
read:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
name: read
url: jdbc:mysql://localhost:3306/test_read?useUnicode=true&characterEncoding=UTF8&useSSL=true
# jdbc-url: jdbc:mysql://localhost:3306/test_read?useUnicode=true&characterEncoding=UTF8&useSSL=true
username: root
password: 123456
# 使用druid数据源
filters: stat,wall
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
connectionProperties: druid.stat.mergeSql=true
#模板引擎
# freemarker:
#关闭缓存
# cache: false
# request-context-attribute: request
#模板加载的位置
# template-loader-path: classpath:/templates
#前缀
# suffix: .htm
#后缀
# prefix: /htm/
3. 数据源的 java 配置类
3.1 WriteDataSourceConfig.java
/**
* 使用 druid-starter 方式配置
* @ClassName: WriteDataSourceConfig
* @author Huangzhijin
* @date 2018年6月21日
*
*/
@Configuration
@MapperScan(basePackages=WriteDataSourceConfig.PACKAGE , sqlSessionTemplateRef="baseSqlSessionTemplate" )
public class WriteDataSourceConfig {
/** 精确到具体的目录,以便和其他目录隔离 */
static final String PACKAGE = "com.hzj.demo.mapper.write";
/** mapper的地址 */
static final String MAPPER_LOCATION = "classpath:com/hzj/demo/mapper/write/*.xml";
/** 类型别名的地址 */
static final String TYPE_ALIASES_PACKAGE = "com.hzj.demo.model";
/*
等效于 xml 中 init-method="init" destroy-method="close"
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
*/
@Bean(name = "baseDataSource" , initMethod="init" , destroyMethod="close" )
@ConfigurationProperties(prefix = "spring.datasource.druid.base")
@Primary
public DataSource dataSource() {
/* //旧版配置实现方式 //指定使用的数据库链接池类型
return DataSourceBuilder.create().type( com.alibaba.druid.pool.DruidDataSource.class ).build();
*/
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "baseTransactionManager")
@Primary
public DataSourceTransactionManager setTransactionManager(@Qualifier("baseDataSource") DataSource dataSource) {
return new DataSourceTransactionManager( dataSource );
}
@Bean(name = "baseSqlSessionFactory")
@Primary
public SqlSessionFactory setSqlSessionFactory(@Qualifier("baseDataSource") DataSource dataSource,@Qualifier("pageHelper")Interceptor pageHelper ) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
//数据源
bean.setDataSource(dataSource);
// mapper.xml 文件扫描
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources( WriteDataSourceConfig.MAPPER_LOCATION ));
//设置vfs类型为 springboot类型
// IMPORTANT: we MUST set the 'VFS',
// otherwise if you run this project as a 'executable jar', then mybatis will throw an exception saying that it can not find java POJO
bean.setVfs( SpringBootVFS.class );
//扫描实体类并配置别名
bean.setTypeAliasesPackage( TYPE_ALIASES_PACKAGE );
//pagehelper 拦截器分页
bean.setPlugins( new Interceptor[]{ pageHelper } );
return bean.getObject();
}
@Bean(name = "baseSqlSessionTemplate")
@Primary
public SqlSessionTemplate setSqlSessionTemplate(@Qualifier("baseSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
3.2 ReadDataSourceConfig.java
package com.hzj.demo.config.starter;
import javax.sql.DataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.data.annotation.TypeAlias;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
/**
* @ClassName: ReadDataSourceConfig
* @author Huangzhijin
* @date 2018年6月21日
*
*/
@Configuration
@MapperScan(basePackages= ReadDataSourceConfig.PACKAGE , sqlSessionTemplateRef="readSqlSessionTemplate" )
public class ReadDataSourceConfig {
//精确到具体的目录,以便和其他目录隔离
static final String PACKAGE = "com.hzj.demo.mapper.read";
//mapper的地址
static final String MAPPER_LOCATION = "classpath:com/hzj/demo/mapper/read/*.xml";
static final String TYPE_ALIASES_PACKAGE ="com.hzj.demo.model";
/*
等效于 xml 中 init-method="init" destroy-method="close"
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
*/
@Bean(name = "readDataSource" , initMethod="init" , destroyMethod="close")
@ConfigurationProperties(prefix = "spring.datasource.druid.read")
public DataSource setDataSource() {
/*return DataSourceBuilder.create().type( com.alibaba.druid.pool.DruidDataSource.class ).build();*/
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "readTransactionManager")
public DataSourceTransactionManager setTransactionManager(@Qualifier("readDataSource") DataSource dataSource) {
return new DataSourceTransactionManager( dataSource );
}
@Bean(name = "readSqlSessionFactory")
public SqlSessionFactory setSqlSessionFactory(
@Qualifier("readDataSource") DataSource dataSource,
@Qualifier("pageHelper")Interceptor pageHelper ) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources( WriteDataSourceConfig.MAPPER_LOCATION ));
//设置vfs类型为 springboot类型
// IMPORTANT: we MUST set the 'VFS',
// otherwise if you run this project as a 'executable jar', then mybatis will throw an exception saying that it can not find java POJO
bean.setVfs( SpringBootVFS.class );
//扫描实体类并配置别名
bean.setTypeAliasesPackage( TYPE_ALIASES_PACKAGE );
//pagehelper 拦截器分页
bean.setPlugins( new Interceptor[]{ pageHelper } );
return bean.getObject();
}
@Bean(name = "readSqlSessionTemplate")
public SqlSessionTemplate setSqlSessionTemplate(@Qualifier("readSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
4. fastjson 整合 springboot 配置类 FastJsonMessageConverterConfig.java
package com.hzj.demo.config;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
/**
*
* @ClassName: FastJsonMessageConverterConfig
* @author Huangzhijin
* @date 2018年6月21日
*
*/
@Configuration
public class FastJsonMessageConverterConfig {
/**
* 默认的配置 FastJson 返回日期格式化的规则
*/
private static String DefaultDateFormat = "yyyy-MM-dd";
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters(){
//1.需要定义一个convert转换消息的对象;
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
//2:添加fastJson的配置信息;
FastJsonConfig fastJsonConfig = new FastJsonConfig();
//fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); //开发环境下使用,生产环境不适用
fastJsonConfig.setFeatures(Feature.AllowArbitraryCommas);
fastJsonConfig.setFeatures(Feature.AllowUnQuotedFieldNames);
fastJsonConfig.setFeatures(Feature.DisableCircularReferenceDetect);
fastJsonConfig.setDateFormat( DefaultDateFormat );
fastJsonConfig.setCharset( Charset.forName("UTF-8") ); //编码格式
//3处理中文乱码问题
List<MediaType> fastMediaTypes = new ArrayList<>();
fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8); //application/json;charset=UTF-8
//4.在convert中添加配置信息. //组装 FastJsonHttpMessageConverter 对象
fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
HttpMessageConverter<?> converter = fastJsonHttpMessageConverter;
//组装对象成 collection
Collection<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>(1);
converters.add(converter);
//5.创建 HttpMessageConverters 对象,并指定使用了的 converter 集合 //启用默认的消息转换类,并指定自定义的消息转换类
HttpMessageConverters httpMessageConverters = new HttpMessageConverters( true , converters);
//返回最终装配好的对象
return httpMessageConverters;
}
}
5. mybatis PageHelper 整合 springboot
package com.hzj.demo.config;
import java.util.Properties;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.github.pagehelper.PageHelper;
/**
*
* @ClassName: MybatisPageHelperConfig
* @author Huangzhijin
* @date 2018年6月21日
*
*/
@Configuration
public class MybatisPageHelperConfig {
@Bean( name = "pageHelper" )
public PageHelper pageHelper() {
PageHelper pageHelper = new PageHelper();
//添加配置,也可以指定文件路径
Properties p = new Properties();
/* p.setProperty("offsetAsPageNum", "true");
p.setProperty("rowBoundsWithCount", "true");
p.setProperty("reasonable", "true");
*/
p.setProperty("helperDialect", "mysql");
p.setProperty("reasonable", "true");
p.setProperty("supportMethodsArguments", "true");
p.setProperty("params", "count=countSql");
p.setProperty("autoRuntimeDialect", "true");
pageHelper.setProperties(p);
return pageHelper;
}
}
6. 使用 thymeleaf 作为 html模板 index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
<!-- <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/dist/bootstrap/css/bootstrap.min.css" />
<script type="text/javascript" src="${pageContext.request.contextPath}/dist/jquery-1.11.1.min.js" ></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/dist/bootstrap/js/bootstrap.min.js" ></script>
-->
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet" type="text/css">
<script type="text/javascript" th:src="@{/dist/jquery-1.11.1.min.js}" ></script>
<script type="text/javascript" th:sec="@{/js/bootstrap.min.js}" ></script>
<!-- <script type="text/javascript">
var rootPath="${pageContext.request.contextPath}/";
</script> -->
<script type="text/javascript" th:inline="javascript" >
// var basePath = /*[[${#httpServletRequest.getScheme() + "://" + #httpServletRequest.getServerName() + ":" + #httpServletRequest.getServerPort() + #httpServletRequest.getContextPath()}]]*/ ;
var rootPath = /*[[${#httpServletRequest.getScheme() + "://" + #httpServletRequest.getServerName() + ":" + #httpServletRequest.getServerPort() + #httpServletRequest.getContextPath()}]]*/;
</script>
</head>
<body>
<h1>首页信息</h1>
<!-- <div>
<p> 头部:<span><%= request.getHeader("User-Agent") %></span> </p>
<p> 客户端IP:<span><%= request.getRemoteAddr() %></span> </p>
<p> 客户端的主机名:<span><%= request.getRemoteHost() %></span> </p>
<p> 客户端的端口:<span><%= request.getRemotePort() %></span> </p>
<p> 客户端的用户:<span><%= request.getRemoteUser() %></span> </p>
<p> 服务器IP:<span><%= request.getLocalAddr() %></span> </p>
<p> 服务器端口:<span><%= request.getLocalPort() %></span> </p>
</div> -->
<div>
<p> 头部:<span>[[${#httpServletRequest.getHeader("User-Agent")}]] </span> </p>
<p> 客户端IP:<span>[[${#httpServletRequest.getRemoteAddr()}]]</span> </p>
<p> 客户端的主机名:<span>[[${#httpServletRequest.getRemoteHost()}]]</span> </p>
<p> 客户端的端口:<span>[[${#httpServletRequest.getRemotePort() }]]</span> </p>
<p> 客户端的用户:<span>[[${#httpServletRequest.getRemoteUser() }]]</span> </p>
<p> 服务器IP:<span>[[${#httpServletRequest.getLocalAddr() }]]</span> </p>
<p> 服务器端口:<span>[[${#httpServletRequest.getLocalPort() }]]</span> </p>
</div>
<h2>当前Tomcat端口:[[${#httpServletRequest.getLocalPort() }]]</h2>
<hr/>
<hr/>
<div class="row">
<div class="col-sm-12">
<!-- <c:if test="${user != null }">
<span>${ user.username },欢饮您。${ user.createDate }</span>
</c:if>
<c:if test="${user == null }">
<form id="loginForm">
<table>
<tr>
<td>
<input type="text" name="account" value="admin" />
</td>
<td>
<input type="password" name="password" value="123456" />
</td>
<td>
<input type="button" id="mybutton" value="登陆" onclick="login()" />
<button type="button" class="btn btn-default" onclick="login();" >登录</button>
</td>
</table>
</form>
</c:if> -->
<!-- <c:if test="${user == null }">
<form id="loginForm" >
<table>
<tr>
<td>
<input type="text" name="account" value="admin" />
</td>
<td>
<input type="password" name="password" value="123456" />
</td>
<td>
<input type="button" id="mybutton" value="登陆" onclick="login()" />
<button type="button" class="btn btn-default" onclick="login();" >登录</button>
</td>
</table>
</form>
</c:if> -->
<div th:if="${session.user}" > <span th:text="${ session.user.username }"></span>,欢饮您。<span th:text="${#dates.format(session.user.createDate, 'yyyy-MM-dd')}"></span></div>
<form id="loginForm" th:unless="${session.user}" >
<table>
<tr>
<td>
<input type="text" name="account" value="admin" />
</td>
<td>
<input type="password" name="password" value="123456" />
</td>
<td>
<!-- <input type="button" id="mybutton" value="登陆" onclick="login()" /> -->
<button type="button" class="btn btn-default" onclick="login();" >登录</button>
</td>
</table>
</form>
</div>
</div>
<hr/>
<h1>查询结果展示</h1>
<hr/>
<div class="row">
<div class="col-sm-12">
<table class="table table-responsive" style="text-align: center;width: 100%;">
<tr>
<th>姓名</th>
<th>年龄</th>
<th>部门ID</th>
<th>性别</th>
<th>电话</th>
<th>创建时间</th>
</tr>
<tbody id="body">
</tbody>
</table>
</div>
</div>
<script type="text/javascript">
var url= rootPath +"/user/page/1/2";
$.post(url,{},function(json){
var html ="";
var rows = json.rows ;
$.each(rows,function(index,item){
html += "<tr>" ;
html += "<td>" + item.username +"</td>" ;
html += "<td>" + item.age +"</td>";
html += "<td>" + item.departmentId + " </td>";
html += "<td>" + item.sex + "</td>";
html += "<td>" + item.phone +"</td>";
html += "<td>" + item.createDate +"</td>";
html += "</tr>" ;
});
html += "<tr>" ;
// html += "<td colspan='6'>-----当前页码---"+ json.pageNum +"----总页数----"+ json.pageSize +" ----startRow---"+ json.startRow +" ---endRow--"+ json.endRow+" ----total--"+ json.total +" ----pages---"+ json.pages +"</td>" ;
html += " <td>当前页码:"+ json.pageNum +"</td>";
html += " <td>总页数:"+ json.pageSize +"</td>";
html += " <td>开始记录数:"+ json.startRow +"</td>";
html += " <td>结束记录数:"+ json.endRow +"</td>";
html += " <td>总行数:"+ json.total +"</td>";
html += " <td>总页数:"+ json.pages +"</td>";
html += "</tr>" ;
$("#body").html("");
$("#body").html(html);
},"json");
function login(){
var obj = $("#loginForm").serializeArray();
var url = rootPath+ "/user/login";
$.post(url , obj , function( json ){
console.log( JSON.stringify( json ) );
if( json && json.success ){
alert( json.msg );
window.top.location.reload();
}else{
alert( "登录失败" );
}
} ,"json");
}
</script>
</body>
</html>
7. controller 代码
7.1 PageController
package com.hzj.demo.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @ClassName: PageController
* @author Huangzhijin
* @date 2018年6月21日
*
*/
@Controller
@RequestMapping("/page")
public class PageController {
@GetMapping("")
public String index() {
return "index";
}
}
7.2 UserController
package com.hzj.demo.web;
import com.hzj.demo.common.MessageDTO;
import com.hzj.demo.common.PageWrapper;
import com.hzj.demo.model.User;
import com.hzj.demo.service.UserService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
/**
* 用户控制器
* @date 2018年6月20日
* @author huangzhijin
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Resource(name="userServiceImpl")
private UserService userService;
/**
* restful interface
* @param pageNum
* @param pageSize
* @return
* @date 2018年4月25日
* @author huangzhijin
*/
@RequestMapping("/page/{pageNum}/{pageSize}")
@ResponseBody
public PageWrapper<User> getPage(@PathVariable(value="pageNum")int pageNum,@PathVariable(value="pageSize")int pageSize) {
return userService.listPageUser(pageNum, pageSize);
}
/**
* 用户登陆
* @param session
* @param user
* @return
* @date 2018年5月27日
* @author huangzhijin
*/
@PostMapping("/login")
@ResponseBody
public MessageDTO login(HttpSession session , User user ) {
MessageDTO dto = new MessageDTO();
User loginUser = userService.selectUserByAccountAndPassword(user);
if ( loginUser == null ){
dto.setSuccess(false);
dto.setMsg("登陆失败,账号或密码错误");
return dto;
}
session.setAttribute("user" , loginUser );
dto.setSuccess(true);
dto.setMsg("登陆成功");
return dto;
}
}
8. service 代码
package com.hzj.demo.service.impl;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.hzj.demo.common.PageWrapper;
import com.hzj.demo.mapper.write.WriteUserMapper;
import com.hzj.demo.model.User;
import com.hzj.demo.service.UserService;
/**
* 用户service
* @date 2018年6月20日
* @author huangzhijin
*/
@Service( "userServiceImpl")
public class UserServiceImpl implements UserService{
@Autowired
private WriteUserMapper dao;
@Override
public PageWrapper<User> listPageUser(Integer pageNum , Integer pageSize) {
if ( pageSize == null || pageNum == null ) {
return null;
}
// PageHelper.startPage 后的第一条 select 语句会自动分页
Page<Object> pageResult = PageHelper.startPage( pageNum.intValue() , pageSize.intValue() );
//aaascasdas
List<User> users = dao.selectAll();
PageWrapper<User> pageModel = new PageWrapper<User>( pageResult , users );
return pageModel ;
}
/*
*
* <p>Title: selectUserByAccountAndPassword</p>
* <p>Description: </p>
* @see com.hzj.demo.service.UserService#selectUserByAccountAndPassword(com.hzj.demo.model.User)
*/
@Override
public User selectUserByAccountAndPassword(User user) {
if ( user == null || StringUtils.isEmpty( user.getAccount() )
|| StringUtils.isEmpty( user.getPassword() ) ){
return null;
}
return dao.selectUserByAccountAndPassword(user);
}
}
9. mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.hzj.demo.mapper.write.WriteUserMapper" >
<resultMap id="BaseResultMap" type="com.hzj.demo.model.User" >
<id column="user_id" property="userId" jdbcType="INTEGER" />
<result column="username" property="username" jdbcType="VARCHAR" />
<result column="age" property="age" jdbcType="TINYINT" />
<result column="department_id" property="departmentId" jdbcType="INTEGER" />
<result column="sex" property="sex" jdbcType="CHAR" />
<result column="phone" property="phone" jdbcType="VARCHAR" />
<result column="account" property="account" jdbcType="VARCHAR" />
<result column="password" property="password" jdbcType="VARCHAR" />
<result column="create_date" property="createDate" />
<result column="update_date" property="updateDate" />
</resultMap>
<sql id="Base_Column_List" >
user_id, username, age, department_id, sex, phone ,account ,password ,create_date , update_date
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from tb_user
where user_id = #{userId,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from tb_user
where user_id = #{userId,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.hzj.demo.model.User" >
insert into tb_user (user_id, username, age,
department_id, sex, phone
)
values (#{userId,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{age,jdbcType=TINYINT},
#{departmentId,jdbcType=INTEGER}, #{sex,jdbcType=CHAR}, #{phone,jdbcType=VARCHAR}
)
</insert>
<insert id="insertSelective" parameterType="com.hzj.demo.model.User" >
insert into tb_user
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="userId != null" >
user_id,
</if>
<if test="username != null" >
username,
</if>
<if test="age != null" >
age,
</if>
<if test="departmentId != null" >
department_id,
</if>
<if test="sex != null" >
sex,
</if>
<if test="phone != null" >
phone,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="userId != null" >
#{userId,jdbcType=INTEGER},
</if>
<if test="username != null" >
#{username,jdbcType=VARCHAR},
</if>
<if test="age != null" >
#{age,jdbcType=TINYINT},
</if>
<if test="departmentId != null" >
#{departmentId,jdbcType=INTEGER},
</if>
<if test="sex != null" >
#{sex,jdbcType=CHAR},
</if>
<if test="phone != null" >
#{phone,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.hzj.demo.model.User" >
update tb_user
<set >
<if test="username != null" >
username = #{username,jdbcType=VARCHAR},
</if>
<if test="age != null" >
age = #{age,jdbcType=TINYINT},
</if>
<if test="departmentId != null" >
department_id = #{departmentId,jdbcType=INTEGER},
</if>
<if test="sex != null" >
sex = #{sex,jdbcType=CHAR},
</if>
<if test="phone != null" >
phone = #{phone,jdbcType=VARCHAR},
</if>
</set>
where user_id = #{userId,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.hzj.demo.model.User" >
update tb_user
set username = #{username,jdbcType=VARCHAR},
age = #{age,jdbcType=TINYINT},
department_id = #{departmentId,jdbcType=INTEGER},
sex = #{sex,jdbcType=CHAR},
phone = #{phone,jdbcType=VARCHAR}
where user_id = #{userId,jdbcType=INTEGER}
</update>
<select id="selectAll" resultMap="BaseResultMap" >
select * from tb_user
</select>
<select id="selectUserByAccountAndPassword" resultMap="BaseResultMap" parameterType="user" >
select * from tb_user where account=#{account} and password =#{password} limit 1
</select>
</mapper>
10. 运行效果
11. 项目目录结构
参考资料:
Druid 官方文档 Druid-Springboot-starter 文档