目录
4. Spring配置文件 spring-context.xml
17. Spring Validation 表单验证(服务端)
1.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">
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.qf.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.hideout.hello.maven.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/servlet/hello</url-pattern>
</servlet-mapping>
</web-app>
2.pom.xml
<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.lusifer</groupId>
<artifactId>project</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<dependencies>
</dependencies>
<project>
3. 依赖导入方式 spring
记得导入lombok的依赖
<?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.hideout</groupId>
<artifactId>hello-spring</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.17.RELEASE</version>
</dependency>
</dependencies>
</project>
4. Spring配置文件 spring-context.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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userService" class="com.hideout.hello.spring.service.impl.UserServiceImpl" />
</beans>
5.log4j.properties
log4j.rootLogger=INFO, console, file
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File=logs/log.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.A3.MaxFileSize=1024KB
log4j.appender.A3.MaxBackupIndex=10
log4j.appender.file.layout.ConversionPattern=%d %p [%c] - %m%n
6.Spring容器配置
- 1.web.xml配置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-context*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
7. Spring Bean注解配置
spring-context.xml
<context:annotation-config />
<context:component-scan base-package="com.qf.hideout.shop"/>
8.管理依赖的pom.xml
(1)环境变量
<properties>
<!-- 环境配置 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
(2)插件
<build>
<plugins>
<!-- Compiler 插件, 设定 JDK 版本 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
</plugins>
<!-- 资源文件配置 -->
<resources>
<resource>
<directory>src/main/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
9. SpringMvc配置
- 首先要依赖Spring-web-MVC
- 配置一个编码过滤器 web.xml
<filter>
<filter-name>encodingFilter</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>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 再配置一个分发器 web.xml
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-mvc*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
- 创建spring-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: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/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<description>Spring MVC Configuration</description>
<!-- 加载配置属性文件 -->
<context:property-placeholder ignore-unresolvable="true" location="classpath:myshop.properties"/>
<!-- 使用 Annotation 自动注册 Bean,只扫描 @Controller -->
<context:component-scan base-package="com.lusifer.myshop" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 默认的注解映射的支持 -->
<mvc:annotation-driven />
<!-- 定义视图文件解析 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="${web.view.prefix}"/>
<property name="suffix" value="${web.view.suffix}"/>
</bean>
<!-- 静态资源映射 -->
<mvc:resources mapping="/static/**" location="/static/" cache-period="31536000"/>
</beans>
- 创建myshop.properties
#============================#
#==== Framework settings ====#
#============================#
# \u89c6\u56fe\u6587\u4ef6\u5b58\u653e\u8def\u5f84
web.view.prefix=/WEB-INF/views/
web.view.suffix=.jsp
- 在Spring-context.xml中添加
<!-- 使用 Annotation 自动注册 Bean,在主容器中不扫描 @Controller 注解,在 SpringMVC 中只扫描 @Controller 注解。-->
<context:component-scan base-package="com.hideout.my.shop">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
7.在webapp文件夹下创建static文件夹,将assets文件移入static文件夹里;
8.在WEB-INF文件夹下创建views文件夹,将jsp文件放入其中。
10. slf4j依赖导入
<!--slf4j star-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-log4j12.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${jcl-over-slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>${jul-to-slf4j.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!--slf4j end-->
<log4j.version>1.2.17</log4j.version>
<jul-to-slf4j.version>1.7.25</jul-to-slf4j.version>
<jcl-over-slf4j.version>1.7.25</jcl-over-slf4j.version>
<slf4j-log4j12.version>1.7.25</slf4j-log4j12.version>
<slf4j-api.version>1.7.25</slf4j-api.version>
11.拦截器
- 在Spring-MVC.xml中的配置
<!-- 拦截器配置,拦截顺序:先执行后定义的,排在第一位的最后执行。-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**"/>
<mvc:exclude-mapping path="/login"/>
<bean class="com.hideout.my.shop.web.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
- 书写方式
-
步骤
- 实现接口HandlerInterceptor,该接口定义了3个方法preHandle(), postHandle(), afterCompletion()
- perhandle(req,resp);该方法的返回值是布尔类型。相当于初始判断是否符合条件,符合则拦截,不符则放行。
- 当返回值是false时,不再进行后两个方法,拦截;
- 当返回值是true时,放行。
- postHandle(req,resp)该方法主要是执行内处理
- afterCompletion(req,response)主要是是资源清理工作
- perhandle(req,resp);该方法的返回值是布尔类型。相当于初始判断是否符合条件,符合则拦截,不符则放行。
- 实现接口HandlerInterceptor,该接口定义了3个方法preHandle(), postHandle(), afterCompletion()
public class LoginInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
12. Spring 整合 Druid
1.添加依赖
- druid;
- mysql-connector-java;(与MySQL的版本相同)
2.配置数据库连接
(项目名称).properties
# JDBC
# MySQL 8.x: com.mysql.cj.jdbc.Driver
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.connectionURL=jdbc:mysql://localhost:3306/myshop?useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username=root
jdbc.password=123456
# JDBC Pool
jdbc.pool.init=1
jdbc.pool.minIdle=3
jdbc.pool.maxActive=20
# JDBC Test
jdbc.testSql=SELECT 'x' FROM DUAL
3. Spring集成Druid,创建spring-context-druid.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 http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 加载配置属性文件 -->
<context:property-placeholder ignore-unresolvable="true" location="classpath:jdbc.properties"/>
<!-- 数据源配置, 使用 Druid 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 数据源驱动类可不写,Druid默认会自动根据URL识别DriverClass -->
<property name="driverClassName" value="${jdbc.driverClass}"/>
<!-- 基本属性 url、user、password -->
<property name="url" value="${jdbc.connectionURL}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${jdbc.pool.init}"/>
<property name="minIdle" value="${jdbc.pool.minIdle}"/>
<property name="maxActive" value="${jdbc.pool.maxActive}"/>
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="60000"/>
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000"/>
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000"/>
<property name="validationQuery" value="${jdbc.testSql}"/>
<property name="testWhileIdle" value="true"/>
<property name="testOnBorrow" value="false"/>
<property name="testOnReturn" value="false"/>
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="stat"/>
</bean>
</beans>
4. 配置Druid监控中心 ,在web.xml文件中添加
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</servlet-name>
<url-pattern>/druid/*</url-pattern>
</servlet-mapping>
5.检查是否创建成功
访问该网站:检验是否创建成功 (<–可点击)
13.Spring整合MyBatis
1. 添加依赖
- mybatis
- mybatis-spring
- spring-jdbc
2. 配置mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 全局参数 -->
<settings>
<!-- 打印 SQL 语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 使全局的映射器启用或禁用缓存。 -->
<setting name="cacheEnabled" value="false"/>
<!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。 -->
<setting name="aggressiveLazyLoading" value="true"/>
<!-- 是否允许单条 SQL 返回多个数据集 (取决于驱动的兼容性) default:true -->
<setting name="multipleResultSetsEnabled" value="true"/>
<!-- 是否可以使用列的别名 (取决于驱动的兼容性) default:true -->
<setting name="useColumnLabel" value="true"/>
<!-- 允许 JDBC 生成主键。需要驱动器支持。如果设为了 true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。 default:false -->
<setting name="useGeneratedKeys" value="false"/>
<!-- 指定 MyBatis 如何自动映射 数据基表的列 NONE:不映射 PARTIAL:部分 FULL:全部 -->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<!-- 这是默认的执行类型 (SIMPLE: 简单; REUSE: 执行器可能重复使用prepared statements语句;BATCH: 执行器可以重复执行语句和批量更新) -->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!-- 使用驼峰命名法转换字段。 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 设置本地缓存范围 session:就会有数据的共享 statement:语句范围 (这样就不会有数据的共享 ) defalut:session -->
<setting name="localCacheScope" value="SESSION"/>
<!-- 设置 JDBC 类型为空时,某些驱动程序 要指定值, default:OTHER,插入空值时不需要指定类型 -->
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>
</configuration>
3. 配置spring-context-mybatis.xml的spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置 SqlSession -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 用于配置对应实体类所在的包,多个 package 之间可以用 ',' 号分割 -->
<property name="typeAliasesPackage" value="com.hideout.my.shop.domain"/>
<!-- 用于配置对象关系映射配置文件所在目录 -->
<property name="mapperLocations" value="classpath:/mapper/**/*.xml"/>
<property name="configLocation" value="classpath:/mybatis-config.xml"></property>
</bean>
<!-- 扫描 Mapper -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.hideout.my.shop.web.admin.dao" />
</bean>
</beans>
14. MyBatis连接数据库应用
1. 首先建立与数据库中表相对应的的实体类
2. 建立数据访问接口,即dao层
@Repository
//dao层的注解
public interface TbUserDao {
/**
* 查询全部用户信息
* @return
*/
public List<TbUser> selectAll();
}
3.业务逻辑层的接口,即实现。
接口
package com.hideout.my.shop.web.admin.service;
import com.hideout.my.shop.domain.TbUser;
import java.util.List;
public interface TbUserService {
/**
* 查询全部用户信息
* @return
*/
public List<TbUser> selectAll();
}
实现
@Service
public class TbUserServiceImpl implements TbUserService {
@Autowired
private TbUserDao tbUserDao;
@Override
public List<TbUser> selectAll() {
return tbUserDao.selectAll();
}
}
4. 单元测试
(注意导包:spring-test,junit)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-context.xml", "classpath:spring-context-druid.xml", "classpath:spring-context-mybatis.xml"})
public class TbUserServiceTest {
@Autowired
private TbUserDao tbUserDao;
@Test
public void testSelectAll() {
List<TbUser> tbUsers = tbUserDao.selectAll();
for (TbUser tbUser : tbUsers) {
System.out.println(tbUser.getUsername());
}
}
}
15.jQuery Validate表单验证插件(前端)
1.导包
<script src="/static/assets/global/plugins/jquery-validation/js/jquery.validate.min.js" type="text/javascript"></script>
<script src="/static/assets/global/plugins/jquery-validation/js/additional-methods.min.js" type="text/javascript"></script>
<!--中文提示语标记-->
<script src="/static/assets/global/plugins/jquery-validation/js/localization/messages_zh.min.js" type="text/javascript"></script>
<!--自己定义的规则-->
<script src="/static/custom_validation.js" type="text/javascript"></script>
2.创建custom_validation.js文件编写规则(全部copy,根据注释提示做更改)
/**
*自定义表单验证
*/
var Validation = function () {
//手机号格式验证--自定义验证"phone"要与一致
var handlerInit = function () {
jQuery.validator.addMethod("phone", function (value, element) {
var length = value.length;
var mobile = /^(((13[0-9]{1})|(15[0-9]{1}))+\d{8})$/;
return this.optional(element) || (length == 11 && mobile.test(value));
}, "手机格式错误");
}
// basic validation
var handleValidation1 = function(form) {
// for more info visit the official plugin documentation:
// http://docs.jquery.com/Plugins/Validation
var form1 = $('#'+form);
var error1 = $('.alert-danger', form1);
var success1 = $('.alert-success', form1);
form1.validate({
errorElement: 'span', //default input error message container
errorClass: 'help-block help-block-error', // default input error message class
focusInvalid: false, // do not focus the last invalid input
ignore: "", // validate all fields including form hidden input
//自定义规则,与id一致,以防万一请将id与name的值写一致
rules: {
username: {
minlength: 2,
required: true
},
email: {
required: true,
email: true
},
oldPassword: {
minlemgth:3,
required: true
},
phone:{
phone:true
},
newPassword:{
minlemgth:3,
required: true
},
rePassword:{
equalTo:"#newPassword",
required: true
}
},
//一下部分不太懂大致的意思,但最好全部写上不要省略
invalidHandler: function (event, validator) { //display error alert on form submit
success1.hide();
error1.show();
App.scrollTo(error1, -200);
},
errorPlacement: function (error, element) { // render error placement for each input type
var cont = $(element).parent('.input-group');
if (cont.size() > 0) {
cont.after(error);
} else {
element.after(error);
}
},
highlight: function (element) { // hightlight error inputs
$(element)
.closest('.form-group').addClass('has-error'); // set error class to the control group
},
unhighlight: function (element) { // revert the change done by hightlight
$(element)
.closest('.form-group').removeClass('has-error'); // set error class to the control group
},
success: function (label) {
label
.closest('.form-group').removeClass('has-error'); // set success class to the control group
},
submitHandler: function (form) {
success1.show();
error1.hide();
}
});
}
//return方法是必须运行部分,把所有的方法写入其中
return {
//规则初始化
init: function (form) {
handleValidation1 (form);
handlerInit();
}
}
}();
//该方法要初始化所有的表单,所有的表单的id都要写入
jQuery(document).ready(function () {
Validation.init('form1');
Validation.init('pwd');
})
16.Junit在spring中的应用
1,导入依赖
<!--Junit star-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<!--有注解时需要导入-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring-test.version}</version>
<scope>test</scope>
</dependency>
<!--Junit END-->
2.测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring-context.xml", "classpath:spring-context-druid.xml", "classpath:spring-context-mybatis.xml"})
public class update {
@Autowired
IUserService userService;
@Test
public void TestUpdate(){
User tbUser = new User();
tbUser.setPassword("dfad");
tbUser.setUsername("pky");
tbUser.setPhone("520");
tbUser.setEmail("df");
tbUser.setId(37);
User user = userService.UserModify(tbUser);
System.out.println(user);
}
17. Spring Validation 表单验证(服务端)
1. 导入依赖
<!--hibernate-validator star-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<!--hibernate-validator end-->
2. 添加工具类(BeanValidator.java)(不需要修改)
package com.hideout.my.shop.commons.validator;
import org.springframework.beans.factory.annotation.Autowired;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* JSR303 Validator(Hibernate Validator)工具类.
* <p>
* ConstraintViolation 中包含 propertyPath, message 和 invalidValue 等信息.
* 提供了各种 convert 方法,适合不同的 i18n 需求:
* 1. List<String>, String 内容为 message
* 2. List<String>, String 内容为 propertyPath + separator + message
* 3. Map<propertyPath, message>
* <p>
* 详情见wiki: https://github.com/springside/springside4/wiki/HibernateValidator
*
* <p>Title: BeanValidator</p>
* <p>Description: </p>
*
* @author Lusifer
* @version 1.0.0
* @date 2018/6/26 17:21
*/
public class BeanValidator {
@Autowired
private static Validator validator;
public static void setValidator(Validator validator) {
BeanValidator.validator = validator;
}
/**
* 调用 JSR303 的 validate 方法, 验证失败时抛出 ConstraintViolationException.
*/
private static void validateWithException(Validator validator, Object object, Class<?>... groups) throws ConstraintViolationException {
Set constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
throw new ConstraintViolationException(constraintViolations);
}
}
/**
* 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 中为 List<message>.
*/
private static List<String> extractMessage(ConstraintViolationException e) {
return extractMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换 Set<ConstraintViolation> 为 List<message>
*/
private static List<String> extractMessage(Set<? extends ConstraintViolation> constraintViolations) {
List<String> errorMessages = new ArrayList<>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getMessage());
}
return errorMessages;
}
/**
* 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 Map<property, message>.
*/
private static Map<String, String> extractPropertyAndMessage(ConstraintViolationException e) {
return extractPropertyAndMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换 Set<ConstraintViolation> 为 Map<property, message>.
*/
private static Map<String, String> extractPropertyAndMessage(Set<? extends ConstraintViolation> constraintViolations) {
Map<String, String> errorMessages = new HashMap<>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.put(violation.getPropertyPath().toString(), violation.getMessage());
}
return errorMessages;
}
/**
* 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 List<propertyPath message>.
*/
private static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), " ");
}
/**
* 辅助方法, 转换 Set<ConstraintViolations> 为 List<propertyPath message>.
*/
private static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations) {
return extractPropertyAndMessageAsList(constraintViolations, " ");
}
/**
* 辅助方法, 转换 ConstraintViolationException 中的 Set<ConstraintViolations> 为 List<propertyPath + separator + message>.
*/
private static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator);
}
/**
* 辅助方法, 转换 Set<ConstraintViolation> 为 List<propertyPath + separator + message>.
*/
private static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations, String separator) {
List<String> errorMessages = new ArrayList<>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getPropertyPath() + separator + violation.getMessage());
}
return errorMessages;
}
/**
* 服务端参数有效性验证
*
* @param object 验证的实体对象
* @param groups 验证组
* @return 验证成功:返回 null;验证失败:返回错误信息
*/
public static String validator(Object object, Class<?>... groups) {
try {
validateWithException(validator, object, groups);
} catch (ConstraintViolationException ex) {
List<String> list = extractMessage(ex);
list.add(0, "数据验证失败:");
// 封装错误消息为字符串
StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
String exMsg = list.get(i);
if (i != 0 ){
sb.append(String.format("%s. %s", i, exMsg)).append(list.size() > 1 ? "<br/>" : "");
} else {
sb.append(exMsg).append(list.size() > 1 ? "<br/>" : "");
}
}
return sb.toString();
}
return null;
}
}
3. 修改实体类,编写规则。
@Length(min = 6, max = 20, message = "用户名长度必须介于 6 和 20 之间")
private String username;
@Length(min = 6, max = 20, message = "密码长度必须介于 6 和 20 之间")
private String password;
@Pattern(regexp = RegexpUtils.PHONE, message = "手机号格式不正确")
private String phone;
@Pattern(regexp = RegexpUtils.EMAIL, message = "邮箱格式不正确")
private String email;
@Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手机号码格式错误")
@NotBlank(message = "手机号码不能为空")
private String phone;
4. JSR提供的校验注解:
JSR提供的校验注解:
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
5. Hibernate Validator提供的校验注解
Hibernate Validator提供的校验注解:
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
6. 书写验证方法,创建工具抽象类AbstractBaseController.java(可以直接用)。
//<T extends AbstractBaseEntity >确保被校验的对象所属的实体类集成该抽象类
//AbstractBaseEntity,这个抽象类自己编写,注意该类注解上@data(实现lombok依赖)
public abstract class AbstractBaseController<T extends AbstractBaseEntity > {
//当参数的类型是Model时
protected void addMessage(Model model, String message) {
model.addAttribute(ConstantUtil.MESSAGE, message);
}
//当参数是Redirect Attributes,重定向后请求不改变,保留数据
protected void addMessage(RedirectAttributes redirectAttributes, String message) {
redirectAttributes.addFlashAttribute(ConstantUtil.MESSAGE, message);
}
protected boolean CheckBean(T entity, Model model){
String result = BeanValidator.validator(entity);
// 验证失败
if (StringUtils.isNoneBlank(result)){
if(model instanceof RedirectAttributes) {
RedirectAttributes redirectAttributes = (RedirectAttributes) model;
addMessage(redirectAttributes,result);
}else {
addMessage(model,result);
}
return false;
}
return true;
}
}
7. 校验的实现(控制器所在的类继承抽象类,直接调用AddMessage方法)
@Controller
public class MainController extends AbstractBaseController{
@PostMapping(value = "userinfo/modify")
public String userInfoModify(User user, HttpServletRequest request, RedirectAttributes redirectAttributes){
//验证信息符合要求
if (CheckBean(user,redirectAttributes)){
user = userService.UserModify(user);
request.getSession().setAttribute(ConstantUtil.WEB_KEY_USER,user);
addMessage(redirectAttributes,ConstantUtil.UPDATE_SUCCESS);
}
return "admin/user_info";
}
@PostMapping(value = "updateUserPwd")
public String UpdateUserPwd(String oldPassword, String newPassword, String rePassword, RedirectAttributes redirectAttributes, User user){
String message = userService.UpdatePWD(oldPassword, newPassword, rePassword, user);
addMessage(redirectAttributes,message);
return "redirect:/userinfo#tab_1_3";
}
}
18. 动态Sql
- if
- 当你的查找条件不确定的时候可以用if
<select id="findActiveBlogWithTitleLike" resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
</select>
- choose,when,otherwise
- 相当于java中的switch语句
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
- trim,where,set
- where
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。
如果 where 元素没有按正常套路出牌,我们可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:(在特殊情况下,可以自定义)
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
where 元素主要是用在查询里,
还有一个set元素使用在修改语句中,例子如下:
<update id="updateUserById" parameterType="com.ys.po.User">
UPDATE user AS 'u'
<set>
<if test="username != null and username != ''">
u.username = #{username},
</if>
<if test="sex != null and sex != ''">
u.sex = #{sex}
</if>
</set>
WHERE id=#{id}
</update>
- 模糊查询 (concat,like)
<select id="selectByName" resultType="TbUser">
SELECT
a.id,
a.username,
a.password,
a.phone,
a.email,
a.created,
a.updated AS "update"
FROM
tb_user AS a
WHERE
a.username LIKE CONCAT ('%', #{username}, '%')
</select>
- 定义SQL片段
- 定义
<sql id = "a">
<---被定义的SQL语句片段--->
</sql>
- 引入
<include refid="a"></include>
- foreach语句
<select id="selectUserByListId" parameterType="com.ys.vo.UserVo" resultType="com.ys.po.User">
select * from user
<where>
<!--
collection:指定输入对象中的集合属性 (ids--是一个关于id 的集合)
item:每次遍历生成的对象
open:开始遍历时的拼接字符串
close:结束时拼接的字符串
separator:遍历对象之间需要拼接的字符串
select * from user where 1=1 and (id=1 or id=2 or id=3)
-->
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id=#{id}
</foreach>
</where>
</select>
19. dataTables
什么是dataTable
dataTable 是一个jQuery表格插件,它主要有以下几个功能:
- 分页,即时搜索和排序
- 几乎支持任何数据源:DOM, javascript, Ajax 和 服务器处理
- 支持不同主题 DataTables, jQuery UI, Bootstrap, Foundation
- 各式各样的扩展: Editor, TableTools, FixedColumns
- 丰富多样的option和强大的API
- 支持国际化(可以设置语言)
可参考的文档
如何使用,简略方法
-
导入js,css文件
-
如果使用的是模板,查找table的id,按住Ctrl键找到该table使用的js文件,重写js文件,如果是长长的一串js的代码在这里格式化一下,然后修改该js,并引入该js,记得修改table的id,具体写法可参考这里
-
在前端的网页写一个$(function(){})方法,调用js里的方法,具体写法可参考这里
-
ajax 里记得填写url地址,JS会自动接收地址
-
项目记得添加Jackson依赖,因为ajax接收的数据是Jackson格式的。
-
封装一个DataTables数据源参考这里
EG:
- 部分jsp文件
<div class="table-container">
<table class="table table-striped table-bordered table-hover table-checkable" id="datatable_me">
<thead>
<th width="5%">
<label class="mt-checkbox mt-checkbox-single mt-checkbox-outline">
<input type="checkbox" class="group-checkable" data-set="#sample_2 .checkboxes" />
<span></span>
</label>
</th>
<th width="15%"> 用户名</th>
<th width="15%"> 邮箱 </th>
<th width="15%"> 电话 </th>
<th width="15%">更新时间 </th>
<th width="30%"> 操作 </th>
</thead>
</table>
</div>
- 重写的js文件
var TableDatatablesAjax_me = function() {
InitDateTablesAjax = function(url, columns) {
var grid = new Datatable;
grid.init({
src: $("#datatable_me"),
/**
* 数据装载成功后的回调
* @param grid DataTable
* @param response 服务器返回的 JSON 数据
*/
onSuccess: function(grid, response) {},
/**
* 请求失败的回调
* @param grid
*/
onError: function(grid) {},
/**
* 装载完 Ajax 数据之后的回调
* @param grid
*/
onDataLoad: function(grid) {},
loadingMessage: "加载中...",
dataTable: {
"lengthMenu": [[10, 20, 50, 100, 150, -1], [10, 20, 50, 100, 150, "All"]],
"pageLength": 5,
"ajax": {
url: url,
},
/**
* 启用排序true
*/
"dom": "<'row' <'col-md-12'B>><'row'<'col-md-6 col-sm-12'l><'col-md-6 col-sm-12'f>r><'table-scrollable't><'row'<'col-md-5 col-sm-12'i><'col-md-7 col-sm-12'p>>", // horizobtal scrollable datatable
"pagingType": 'bootstrap_extended', // pagination type
"ordering": false,
"searching": false,
"columns": columns,
"lengthChange": false,
"language": {
"metronicAjaxRequestGeneralError": "无法完成请求,请检查你的网络",
"sProcessing": "处理中...",
"sLengthMenu": "显示 _MENU_ 项结果",
"sZeroRecords": "没有匹配结果",
"sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
"sInfoEmpty": "显示第 0 至 0 项结果,共 0 项",
"sInfoFiltered": "(由 _MAX_ 项结果过滤)",
"sInfoPostFix": "",
"sSearch": "搜索:",
"sUrl": "",
"sEmptyTable": "表中数据为空",
"sLoadingRecords": "载入中...",
"sInfoThousands": ",",
"oPaginate": {
"sFirst": "首页",
"sPrevious": "上页",
"sNext": "下页",
"sLast": "末页",
"page": "页码",
"pageOf": "/"
},
"oAria": {
"sSortAscending": ": 以升序排列此列",
"sSortDescending": ": 以降序排列此列"
},
},
buttons: [],
},
});
return grid;
}
return{
init: function(url , columns){
return InitDateTablesAjax(url , columns)
}
}
}();
- jsp中的调用函数书写
$(function () {
TableDatatablesAjax_me.init("/user/list/page", [
{"data": function (row, type,set,meta) {
return '<label class="mt-checkbox mt-checkbox-single mt-checkbox-outline">' +
' <input type="checkbox" class="checkboxes" value="1">' +
' <span></span>' +
' </label>'
}},
{ "data": "username" },
{ "data": "email" },
{ "data": "phone" },
{ "data": "updated" },
{ "data":function (row, type, set, meta) {
return '<a href="/user/list/getById?id='+row.id+' " class="btn btn-circle green">编辑' +
' <i class="fa fa-font"></i>' +
' </a>' +
' <a href="/user/list/lookUser?id='+row.id+' " class="btn btn-circle blue">' +
' <i class="fa fa-file-o"></i> 查看' +
' </a>' +
' <a onclick="del('+ row.id+')" class="btn btn-circle purple mt-sweetalert">' +
' <i class="fa fa-times"></i> 删除' +
' </a>';
}
}
]);
});
- controller
@ResponseBody
@PostMapping(value = "page")
public DataTable<User> page(User user, HttpServletRequest request){
DataTable<User> dataTable = new DataTable<>();
String strDraw = request.getParameter("draw");
String strStart = request.getParameter("start");
String strLength = request.getParameter("length");
int draw = StringUtils.isBlank(strDraw) ? 1 : Integer.parseInt(strDraw);
int start = StringUtils.isBlank(strStart) ? 0 : Integer.parseInt(strStart);
int length = StringUtils.isBlank(strLength) ? 10 : Integer.parseInt(strLength);
PageInfo<User> pageInfo = userListService.page(user, start, length);
dataTable.setDraw(draw);
dataTable.setRecordsTotal(pageInfo.getTotal());
dataTable.setRecordsFiltered(pageInfo.getTotal());
dataTable.setData(pageInfo.getData());
return dataTable;
}
- 封装一个DataTables数据源
package com.qf.hideout.web.shop.dto;
import com.qf.hideout.web.shop.abstracts.AbstractBaseEntity;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 用于封装 DataTable 数据源
* <p>Title: DataTable</p>
* <p>Description: </p>
*
*/
@Data
public class DataTable<T extends AbstractBaseEntity> implements Serializable {
private int draw;
private int recordsTotal;
private int recordsFiltered;
private List<T> data;
}
20. sweetalert只是Alert的样式框架
具体操作参考该网站
例子:
<a onclick="del(id)" class="btn btn-circle purple mt-sweetalert">
<i class="fa fa-times"></i> 删除
</a>
function del(rid) {
swal({
title: "你是否确定?",
text: "你要删除该数据!",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn-danger",
confirmButtonText: "确定删除",
cancelButtonText: "取消删除",
closeOnConfirm: false,
closeOnCancel: false,
},
function(isConfirm) {
if (isConfirm) {
swal({
title:"操作成功",
text:"你已经删除了该条数据",
confirmButtonClass: "success",
},function () {
$.post("/user/list/detele",{ id: rid });
window.location="/user/list/all";
})
} else {
swal("操作失败", "你已经取消了删除", "error");
}
})
}