校验框架
校验框架入门
表单校验的重要性
- 表单校验保障了数据有效性、安全性
数据可以随意输入,导致错误的结果。后端表单校验的重要性。
表单校验分类
- 校验位置:
- 客户端校验
- 服务端校验
- 校验内容与对应方式:
- 格式校验
- 客户端:使用Js技术,利用正则表达式校验
- 服务端:使用校验框架
- 逻辑校验
- 客户端:使用ajax发送要校验的数据,在服务端完成逻辑校验,返回校验结果
- 服务端:接收到完整的请求后,在执行业务操作前,完成逻辑校验
- 格式校验
表单校验规则
- 长度:例如用户名长度,评论字符数量
- 非法字符:例如用户名组成
- 数据格式:例如Email格式、 IP地址格式
- 边界值:例如转账金额上限,年龄上下限
- 重复性:例如用户名是否重复
表单校验框架
-
JSR(Java Specification Requests):Java 规范提案
303:提供bean属性相关校验规则
-
JSR规范列表
- 企业应用技术
Contexts and Dependency Injection for Java (Web Beans 1.0) (JSR 299)
Dependency Injection for Java 1.0 (JSR 330)@postConstruct, @PreDestroy
Bean Validation 1.0 (JSR 303)
Enterprise JavaBeans 3.1 (includes Interceptors 1.1) (JSR 318)
Java EE Connector Architecture 1.6 (JSR 322)
Java Persistence 2.0 (JSR 317)
Common Annotations for the Java Platform 1.1 (JSR 250)
Java Message Service API 1.1 (JSR 914)
Java Transaction API (JTA) 1.1 (JSR 907)
JavaMail 1.4 (JSR 919) - Web应用技术
Java Servlet 3.0 (JSR 315)
JavaServer Faces 2.0 (JSR 314)
JavaServer Pages 2.2/Expression Language 2.2 (JSR 245)
Standard Tag Library for JavaServer Pages (JSTL) 1.2 (JSR 52)
Debugging Support for Other Languages 1.0 (JSR 45)
模块化 (JSR 294)
Swing应用框架 (JSR 296)
JavaBeans Activation Framework (JAF) 1.1 (JSR 925)
Streaming API for XML (StAX) 1.0 (JSR 173) - 管理与安全技术
Java Authentication Service Provider Interface for Containers (JSR 196)
Java Authorization Contract for Containers 1.3 (JSR 115)
Java EE Application Deployment 1.2 (JSR 88)
J2EE Management 1.1 (JSR 77)
Java SE中与Java EE有关的规范
JCache API (JSR 107)
Java Memory Model (JSR 133)
Concurrency Utilitie (JSR 166)
Java API for XML Processing (JAXP) 1.3 (JSR 206)
Java Database Connectivity 4.0 (JSR 221)
Java Management Extensions (JMX) 2.0 (JSR 255)
Java Portlet API (JSR 286)
- 企业应用技术
-
Web Service技术
Java Date与Time API (JSR 310)
Java API for RESTful Web Services (JAX-RS) 1.1 (JSR 311)
Implementing Enterprise Web Services 1.3 (JSR 109)
Java API for XML-Based Web Services (JAX-WS) 2.2 (JSR 224)
Java Architecture for XML Binding (JAXB) 2.2 (JSR 222)
Web Services Metadata for the Java Platform (JSR 181)
Java API for XML-Based RPC (JAX-RPC) 1.1 (JSR 101)
Java APIs for XML Messaging 1.3 (JSR 67)
Java API for XML Registries (JAXR) 1.0 (JSR 93) -
JCP(Java Community Process):Java社区
-
Hibernate框架中包含一套独立的校验框架hibernate-validator
导入坐标
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.0.Final</version> </dependency>
<!--支持tomcat7--> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.1.Final</version> </dependency>
注意:
tomcat7 :搭配hibernate-validator版本5...Final
tomcat8.5↑ :搭配hibernate-validator版本6...Final
快速使用
** 开启校验**
名称:@Valid 、 @Validated
- @valid : 一般在实体类中校验别的实体类
- @Validated : 一般校验形参
类型:形参注解
位置:处理器类中的实体类类型的方法形参前方
作用:设定对当前实体类类型参数进行校验
范例:
1.编写实体类,存放表单数据。并且设置校验规则
package cn.itcast.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@NotBlank(message = "姓名不能为空")
private String name;
@NotNull(message = "年龄不能为空")//此处不能用NotBlank,因为该注解只能校验字符串,而age是数字
@Max(message = "年龄不能超过100",value = 100)
@Min(message = "年龄不能小于1",value = 1)
private Integer age;
}
2.编写处理器,接受表单数据,并且启用校验
package cn.itcast.controller;
import cn.itcast.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/user")
@CrossOrigin
public class UserController {
@RequestMapping("/reg")
@ResponseBody
public Map method(@Validated User user, Errors errors){//errors中存放校验失败的提示信息
HashMap<Object, Object> map = new HashMap<>();
HashMap<Object, Object> errorInfo = new HashMap<>();//存放字段名对应的错误提示
//判断是否有错误信息
if(errors.hasErrors()){
for (FieldError e : errors.getFieldErrors()) {//errors.getFieldErrors()获取所有的错误信息
//e.getField()表示获取属性名,e.getDefaultMessage()获取错误提示信息
errorInfo.put(e.getField(),e.getDefaultMessage());
}
}
if(errorInfo.size()==0){//没有错误数据
map.put("status",true);
}else{
map.put("status",false);
map.put("errorInfos",errorInfo);
}
return map;
}
}
3.测试,访问 http://localhost/user/reg?name&age 结果如下
设置校验规则
名称:@NotNull、@NotBlank
- @NotNull : 一般用于校验非字符串
- @NoBlank : 一般用于校验字符串
类型:属性注解 等
位置:实体类属性上方
作用:设定当前属性校验规则
范例:
每个校验规则所携带的参数不同,根据校验规则进行相应的调整
具体的校验规则查看对应的校验框架进行获取public class Employee{ @NotNull(message = "姓名不能为空") private String name;//员工姓名 }
3.测试,访问 http://localhost/user/reg?name&age 结果如下
注意:测试的时候必须写清楚发送给服务器哪些字段,如果不写,服务器可能不校验。
{
"errorInfos": {
"name": "姓名不能为空",
"age": "请输入年龄"
},
"status": false
}
获取错误信息
@RequestMapping(value = "/addemployee")
public String addEmployee(@Valid Employee employee, Errors errors, Model model){
System.out.println(employee);
if(errors.hasErrors()){
for(FieldError error : errors.getFieldErrors()){
model.addAttribute(error.getField(),error.getDefaultMessage());
}
return "addemployee.jsp";
}
return "success.jsp";
}
通过形参Errors获取校验结果数据,通过Model接口将数据封装后传递到页面显示
<form action="/addemployee" method="post">
员工姓名:<input type="text" name="name"><span style="color:red">${name}</span><br/>
员工年龄:<input type="text" name="age"><span style="color:red">${age}</span><br/>
<input type="submit" value="提交">
</form>
通过形参Errors获取校验结果数据,通过Model接口将数据封装后传递到页面显示
页面获取后台封装的校验结果信息
多规则校验
- 同一个属性可以添加多个校验器
@NotNull(message = "请输入您的年龄")
@Max(value = 60,message = "年龄最大值不允许超过60岁")
@Min(value = 18,message = "年龄最小值不允许低于18岁")
private Integer age;//员工年龄
- 3种判定空校验器的区别
@Null 限制只能为null
@NotNull 限制必须不为null
@AssertFalse 限制必须为false
@AssertTrue 限制必须为true
@DecimalMax(value) 限制必须为一个不大于指定值的数字
@DecimalMin(value) 限制必须为一个不小于指定值的数字
@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future 限制必须是一个将来的日期
@Max(value) 限制必须为一个不大于指定值的数字
@Min(value) 限制必须为一个不小于指定值的数字
@Past 限制必须是一个过去的日期
@Pattern(value) 限制必须符合指定的正则表达式
@Size(max,min) 限制字符长度必须在min到max之间
@Past 验证注解的元素值(日期类型)比当前时间早
@NotEmpty 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,
@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式
嵌套校验
名称:@Valid
类型:属性注解
位置:实体类中的引用类型属性上方
作用:设定当前应用类型属性中的属性开启校验
范例:
public class Employee {
//实体类中的引用类型通过标注@Valid注解,设定开启当前引用类型字段中的属性参与校验
@Valid
private Address address;
}
注意:开启嵌套校验后,被校验对象内部需要添加对应的校验规则
分组校验
- 同一个模块,根据执行的业务不同,需要校验的属性会有不同
- 新增用户
- 修改用户
- 对不同种类的属性进行分组,在校验时可以指定参与校验的字段所属的组类别
- 定义组(通用)
- 为属性设置所属组,可以设置多个
- 开启组校验
第一步:定义了两个组,一个是注册的时候校验,一个是修改的时候校验
package cn.itcast.group;
public interface RegGroup {
}
Java
package cn.itcast.group;
public interface UpdateUserGroup {
}
第二步:定义User\Address实体类,指定校验规则,并分组校验
规则:注册的时候校验帐号和密码,修改的时候校验密码和地址
Address
package cn.itcast.domain;
import cn.itcast.group.RegGroup;
import cn.itcast.group.UpdateUserGroup;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.NotBlank;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Address {
@NotBlank(message = "省名不能为空",groups = {UpdateUserGroup.class})
/**省的名字*/
private String province;
@NotBlank(message = "城市名不能为空",groups = {UpdateUserGroup.class})
/**城市的名字*/
private String city;
}
User
package cn.itcast.domain;
import cn.itcast.group.RegGroup;
import cn.itcast.group.UpdateUserGroup;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@NotBlank(message = "用户名不能为空",groups = RegGroup.class)
@Pattern(regexp = "^[A-Za-z_@.]{6,10}$",message = "用户名必须是6-10位之间的字母、下划线、@、.",groups = RegGroup.class)
private String username;
@NotBlank(message = "密码不能为空",groups = {RegGroup.class, UpdateUserGroup.class})
@Pattern(regexp = "^[A-Za-z_@.]{6,10}$",message = "密码必须是6-10位之间的字母、下划线、@、.",groups = {RegGroup.class, UpdateUserGroup.class})
private String password;
@Valid()
private Address address;
}
第三步 在controller层,分别定义两个接口,一个是注册接口,使用注册的校验规则,另一个是修改接口,使用修改的校验规则
package cn.itcast.controller;
import cn.itcast.domain.User;
import cn.itcast.group.RegGroup;
import cn.itcast.group.UpdateUserGroup;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/user")
@CrossOrigin
public class UserController {
@RequestMapping("/reg")
@ResponseBody
public Map reg(@Validated(RegGroup.class) User user, Errors errors){//errors中存放校验失败的提示信息
HashMap<Object, Object> map = new HashMap<>();
HashMap<Object, Object> errorInfo = new HashMap<>();//存放字段名对应的错误提示
//判断是否有错误信息
if(errors.hasErrors()){
for (FieldError e : errors.getFieldErrors()) {//errors.getFieldErrors()获取所有的错误信息
//e.getField()表示获取属性名,e.getDefaultMessage()获取错误提示信息
errorInfo.put(e.getField(),e.getDefaultMessage());
}
}
if(errorInfo.size()==0){//没有错误数据
map.put("status",true);
}else{
map.put("status",false);
map.put("errorInfos",errorInfo);
}
return map;
}
@RequestMapping("/update")
@ResponseBody
public Map update(@Validated(UpdateUserGroup.class) User user, Errors errors){//errors中存放校验失败的提示信息
HashMap<Object, Object> map = new HashMap<>();
HashMap<Object, Object> errorInfo = new HashMap<>();//存放字段名对应的错误提示
//判断是否有错误信息
if(errors.hasErrors()){
for (FieldError e : errors.getFieldErrors()) {//errors.getFieldErrors()获取所有的错误信息
//e.getField()表示获取属性名,e.getDefaultMessage()获取错误提示信息
errorInfo.put(e.getField(),e.getDefaultMessage());
}
}
if(errorInfo.size()==0){//没有错误数据
map.put("status",true);
}else{
map.put("status",false);
map.put("errorInfos",errorInfo);
}
return map;
}
}
测试结果
注册:没有校验地址
修改:没有校验帐号
ssm整合
整合流程简介
整合步骤分析
SSM(Spring+SpringMVC+MyBatis)
-
Spring
- 框架基础
-
MyBatis
- mysql+druid+pagehelper
-
Spring整合MyBatis
-
junit测试业务层接口
-
SpringMVC
- rest风格(postman测试请求结果)
- 数据封装json(jackson)
-
Spring整合SpringMVC
- Controller调用Service
-
其他
-
表现层数据封装
-
自定义异常
-
表结构
最重要的5个步骤
-
Spring
-
MyBatis
-
Spring整合MyBatis
-
SpringMVC
-
Spring整合SpringMVC
项目结构搭建
引入依赖
<dependencies>
<!--jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
<!-- servlet3.1规范的坐标 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!--jsp坐标-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!--Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.6</version>
</dependency>
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.3</version>
</dependency>
<!--数据校验,支持tomcat7-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.1.Final</version>
</dependency>
<!--spring的坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!--spring web的坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!--springmvc的坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!--Spring集成Junit测试-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--Spring集成Aspect切面-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<!--Spring 事物-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!--spring连接数据库-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<!--spring集成mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!--spring集成junit-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--jdk编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<!--tomcat插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<!-- tomcat7的插件, 不同tomcat版本这个也不一样 -->
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<!-- 通过maven tomcat7:run运行项目时,访问项目的端口号 -->
<port>80</port>
<!-- 项目虚拟路径 如果配置的, 则访问路径为localhost:8080/-->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
创建dao\service\domain
创建实体类 Account
package cn.itcast.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account {
private Integer id;
private String name;
private Double money;
}
创建 Dao
package cn.itcast.dao;
import cn.itcast.domain.Account;
import java.util.List;
public interface AccountDao {
@Select("select * from account")
List<Account> findAll();
}
创建Service
package cn.itcast.service;
import cn.itcast.domain.Account;
import java.util.List;
public interface AccountService {
List<Account> findAll() ;
}
创建Service实现类
package cn.itcast.service.impl;
import cn.itcast.dao.AccountDao;
import cn.itcast.domain.Account;
import cn.itcast.service.AccountService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Service
public class AccountServiceImpl implements AccountService {
@Autowaired
private AccountDao accountDao;
public List<Account> findAll() {
return accountDao.findAll();
}
}
创建jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring01
jdbc.username=root
jdbc.password=root
Spring整合Mybatis
- 配置包扫描
- 配置数据库连接池
- 集成MyBatis
- 集成分页
- 配置事物
<?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"
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/tx http://www.springframework.org/schema/tx/spring-tx.xsd
">
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
<!--1.配置包扫描-->
<context:component-scan base-package="cn.itcast">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--2.配置数据库连接池-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--3.集成MyBatis-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="typeAliasesPackage" value="cn.itcast.domain"></property>
<!--4.集成分页-->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<prop key="helperDialect">mysql</prop>
<!--reasonable:分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页,
pageNum>pages(超过总数时),会查询最后一页。
默认false 时,直接根据参数进行查询。-->
<prop key="reasonable">true</prop>
</props>
</property>
</bean>
</array>
</property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.itcast.dao"></property>
</bean>
<!--5.配置平台事物管理器,启用事物注解驱动在第一行-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
测试
package cn.itcast.service.impl;
import cn.itcast.service.AccountService;
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;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AccountServiceImplTest {
@Autowired
private AccountService accountService ;
@Test
public void findAll() {
System.out.println(accountService.findAll());
}
}
配置SpringMVC
- 配置包扫描,只扫controller
- 启用springmvc注解
- 静态资源放行
- 配置视图解析器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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">
<!--1.配置包扫描,只扫controller-->
<context:component-scan base-package="cn.itcast">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--2.启用springmvc注解-->
<mvc:annotation-driven/>
<!--3.静态资源放行-->
<mvc:default-servlet-handler/>
<!--4.配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
配置web.xml
配置web核心三大组件
- listener:ContextLoaderListener
- filter:CharacterEncodingFilter
- servlet:DispatcherServlet
<?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">
<display-name>Archetype Created Web Application</display-name>
<!--
1.listener:ContextLoaderListener
2.filter:CharacterEncodingFilter
3.servlet:DispatcherServlet
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
创建Result统一返回数据格式
Result
package cn.itcast.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result {
/**操作成功或失败的状态*/
private boolean flag;
/**小时提示*/
private String message;
/**消息状态码*/
private Integer code;
/**数据*/
private Object data;
}
常量类
package cn.itcast.constant;
public class CodeConstant {
//账户模块以1开头,长度是6
/**查询账户成功*/
public static final Integer ACCOUNT_GET_SUCCESS = 100001;
/**查询账户失败*/
public static final Integer ACCOUNT_GET_ERROR = 100002;
}
package cn.itcast.constant;
public class MessageConstant {
//账户模块以1开头,长度是6
/**查询账户成功*/
public static final String ACCOUNT_GET_SUCCESS = "查询账户成功";
/**查询账户失败*/
public static final String ACCOUNT_GET_ERROR = "查询账户失败";
}
创建controller
@RestController
@RequestMapping("/account")
public class AccountController {
@Autowired
private AccountService accountService;
@RequestMapping
public Result findAll(){
try {
List<Account> list = accountService.findAll();
return new Result(true, MessageConstant.ACCOUNT_GET_SUCCESS, CodeConstant.ACCOUNT_GET_SUCCESS,list);
} catch (Exception e) {
e.printStackTrace();
return new Result(false,MessageConstant.ACCOUNT_GET_ERROR,CodeConstant.ACCOUNT_GET_ERROR,null);
}
}
}
统一异常处理
自定义异常
设定自定义异常,封装程序执行过程中出现的问题,便于表现层进行统一的异常拦截并进行处理
- BusinessException
- SystemException
自定义异常消息返回时需要与业务正常执行的消息按照统一的格式进行处理
定义BusinessException
public class BusinessException extends RuntimeException {
//自定义异常中封装对应的错误编码,用于异常处理时获取对应的操作编码
private Integer code;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public BusinessException(Integer code) {
this.code = code;
}
public BusinessException(String message, Integer code) {
super(message);
this.code = code;
}
public BusinessException(String message, Throwable cause,Integer code) {
super(message, cause);
this.code = code;
}
public BusinessException(Throwable cause,Integer code) {
super(cause);
this.code = code;
}
public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace,Integer code) {
super(message, cause, enableSuppression, writableStackTrace);
this.code = code;
}
}
@GetMapping("/{uuid}")
public Result get(@PathVariable Integer uuid){
User user = userService.get(uuid);
//模拟出现异常,使用条件控制,便于测试结果
if (uuid == 10 ) throw new BusinessException("查询出错啦,请重试!",Code.GET_ERROR);
return new Result(null != user ?Code.GET_OK: Code.GET_ERROR,user);
}
返回消息兼容异常信息
@Component
@ControllerAdvice
public class ProjectExceptionAdivce {
@ExceptionHandler(BusinessException.class)
@ResponseBody
//对出现异常的情况进行拦截,并将其处理成统一的页面数据结果格式
public Result doBusinessException(BusinessException e){
return new Result(e.getCode(),e.getMessage());
}
}
纯注解开发SSM
用注解替代applicationContext.xml
同前期设置,添加事务注解驱动
@Configuration
//扫描组件,排除SpringMVC对应的bean,等同于<context:component-scan />
@ComponentScan(value = "com.itheima",excludeFilters = {
@ComponentScan.Filter(type= FilterType.ANNOTATION,classes = {Controller.class})})
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MyBatisConfig.class})
//等同于<tx:annotation-driven transaction-manager="txManager"/>,导入的默认名称为transactionManager
@EnableTransactionManagement
public class SpringConfig {
//等同于<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
@Bean("transactionManager")
public DataSourceTransactionManager getDataSourceTxManager(@Autowired DataSource dataSource){
DataSourceTransactionManager dtm = new DataSourceTransactionManager();
//等同于<property name="dataSource" ref="dataSource"/>
dtm.setDataSource(dataSource);
return dtm;
}
}
用注解替代spring-mvc.xml
-
同前期设置,添加@EnableWebMvc注解
@Configuration @ComponentScan("com.itheima.controller") @EnableWebMvc public class SpringMvcConfig implements WebMvcConfigurer { }
-
EnableWebMvc
- 支持ConversionService的配置,可以方便配置自定义类型转换器
- 支持@NumberFormat注解格式化数字类型
- 支持@DateTimeFormat注解格式化日期数据,日期包括Date,Calendar,JodaTime(JodaTime要导包)
- 支持@Valid的参数校验(需要导入JSR-303规范)
- 配合第三方jar包和SpringMVC提供的注解读写XML和JSON格式数据