Spring和SpringMVC使用总结
环境搭建
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</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>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<port>80</port>
<uriEncoding>utf-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>
web.xml
<!--加载Spring配置文件到容器-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:beans.xml</param-value>
</context-param>
<!--监听创建-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--创建前端控制器 加载Springmvc容器-->
<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>
<!--过滤器-->
<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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
beans.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">
<!--spring包扫描-->
<context:component-scan base-package="com.ybb.service"/>
<!--加载外部配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--创建工厂,加载连接池,包起别名-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.ybb.domain"/>
</bean>
<!--连接池对象-->
<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>
<!--dao映射关系-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ybb.dao"/>
</bean>
</beans>
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: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 https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--包扫描-->
<context:component-scan base-package="com.ybb.controller"/>
<!--json格式转换-->
<mvc:annotation-driven/>
<!--配置完后静态和非静态不同访问-->
<mvc:default-servlet-handler/>
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/aaa/aa"/>
<bean class="com.ybb.Interceptors.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
<!--文件上传-->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"/>
</beans>
一 SpringMVC Controller
1.在类打上@Controller注解
2.在方法上添加@RequestMapping注解
3.在springmvc的配置文件上开启注解扫描
4.如果不想把返回值当前页面转发,设置@ResponseBody把返回值当成参数
5.记得SpringMVC中配置注解扫描扫描
<context:component-scan base-package="com.ybb.controller"/>
这样配置访问路径 localhost:8080/aaa/aa
静态资源
/: 会匹配到url路径(/index),静态资源(.html,.js等),也会匹配到.jsp
上面配置的拦截路径是/,会拦截所有的资源,如果想访问index.html或者xxx.jsp这种静态资源也会当做url的映射路径来匹配,导致静态页面使用不了
在SpringMVC中配置
<mvc:default-servlet-handler/>
框架会自动处理,先匹配url是否有相同的路径,有就交给方法处理,没有当做静态资源
前后台传参
1.同名匹配
user中有String name和Integer age属性,传入的参数是键值对形式的,如果刚好有name,age会自动匹配封装
@RequestMapping("/ajaxController1")
@ResponseBody
public String ajaxController(User user){
System.out.println(user);
return "user";
}
2.地址栏传参
用pathVariable标签,指定键的id来封装赋值给形参
这是Restful风格配置
@RequestMapping("/delete/{id}")
public void delete(@PathVariable("id") Long id){
System.out.print(id);
}
中文乱码
固定格式,没啥好说的
<!--编码过滤器 只对post请求有效-->
<filter>
<filter-name>characterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>endoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
文件上传下载
文件上传需要的三要素
post请求
enctype=“multipart/form-data”
<input type="file" name="file"/>
也就是需要个表单来提交
<form action="/fileupload" method="post" enctype="multipart/form-data">
上传LOGO: <input type="file" name="file"/><br/>
<input type="submit" value="上传"/>
</form>
SpringMVC中开启文件上传,固定格式
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"/>
@Controller
public class file {
@RequestMapping("/fileupload")
@ResponseBody
public void fileload(MultipartFile file) throws IOException {
file.transferTo(new File("aaa.png"));
}
}
拦截器
手写一个类实现HandlerInterceptor接口,重写方法,然后放入容器中,设置下拦截的路径即可
因为会在Spring-mvc中注册,所以不需要在类上配置注解
public class MyInterceptor implements HandlerInterceptor {
//前置
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("111111111111");
return true;
}
//后置
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("22222222222");
}
//最终
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("33333333333");
}
}
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/aaa/aa"/>
<bean class="com.ybb.Interceptors.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
返回json格式
打开上帝模式
<!--json格式转换-->
<mvc:annotation-driven/>
需要导入依赖
<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>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
然后返回即可,记得在要返回的方法上写上@ResopnseBody,不然会页面转发
//返回json格式
// 1.在方法的返回值上直接声明要返回的类型,并且加上@ResponseBody注解
@Controller
public class JsonController {
@RequestMapping("/json")
@ResponseBody
public User json() {
User user = new User("CoderZS", "1234");
return user;
}
@RequestMapping("/json1")
@ResponseBody
public List<User> json1() {
User user = new User("CoderZS", "1234",new Date());
List list = new ArrayList<>();
list.add(user);
return list;
}
日期
要让日期按指定格式输出的话,分两种情况
1.后台往前台传json值时(包含日期)
2.前台往后台传参
异步请求
@RequestBody 形参上
从请求体中匹配参数,赋值给形参
@RequestMapping("/ajaxController")
public String ajaxController(@RequestBody String message){
System.out.println(message);
return "page.jsp";
}
跨域访问
@CrossOrigin 方法或者类上 即可
不同ip或者端口中方法相互调用
@RequestMapping("/cross")
@ResponseBody
//使用@CrossOrigin开启跨域访问
//标注在处理器方法上方表示该方法支持跨域访问
//标注在处理器类上方表示该处理器类中的所有处理器方法均支持跨域访问
@CrossOrigin
public User cross(HttpServletRequest request){
System.out.println("controller cross..."+request.getRequestURL());
User user = new User();
user.setName("Jockme");
user.setAge(39);
return user;
}
异常
类上写@COntrollerAdvice,设置当前类为异常处理类
默认加了@Compont注解
@ExceptionHandler 设置指定异常的处理方式
@ControllerAdvice
public class MyException {
@ExceptionHandler(NullPointerException.class)
@ResponseBody
public String doNullException(Exception e){
System.out.println(e);
System.out.println(e.getMessage());
return "空指针";
}
}
自定义话,自己写个类继承RuntimeException,重写方法,然后在异常类中完成调用
//自定义异常继承RuntimeException,覆盖父类所有的构造方法
public class BusinessException extends RuntimeException {
public BusinessException() {
}
public BusinessException(String message) {
super(message);
}
public BusinessException(String message, Throwable cause) {
super(message, cause);
}
public BusinessException(Throwable cause) {
super(cause);
}
public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
Restful
还不懂,以后更新
二 Spring
Loc
Inverse of Control 控制反转
开发
基本以注解和Xml结合使用居多,xml加载配置文件,初始化好方便,注解写类写方法好,配合扫描就可以了。
包扫描和bean(类)
<!--spring包扫描-->
<context:component-scan base-package="com.ybb.service"/>
@Component
@Controller 表现层
@Service 业务层
@Repository 持久层
自动引入引用类型的话@Autowired即可,记得配合扫描dao,才能自动装配进去
<!--dao映射关系-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ybb.dao"/>
</bean>
Aop
面向切面编程
Aop注解开发
1.定义一个类,上面加@Aspect 设置为切面类
2.在Springxml中配置开启aspect注解自动代理 <aop:aspectj-autoproxy/>
3.设置切入点 定义个无业务的方法上配置个切入点路径
4.创建通知,绑定切入点
事务
@Transactional 类,方法,接口 开启事务,就近原则
<!--配置事务管理器-->
<bean id="txMa" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--使用指定使用事务管理器-->
<tx:annotation-driven transaction-manager="transactionManager"/>
配置下事务管理器,指定好后,在类或者方法上@Transactional即可
校验框架
1.1.1 表单校验的重要性
- 表单校验保障了数据有效性、安全性
数据可以随意输入,导致错误的结果。后端表单校验的重要性。
1.1.2 表单校验分类
- 校验位置:
- 客户端校验
- 服务端校验
- 校验内容与对应方式:
- 格式校验
- 客户端:使用Js技术,利用正则表达式校验
- 服务端:使用校验框架
- 逻辑校验
- 客户端:使用ajax发送要校验的数据,在服务端完成逻辑校验,返回校验结果
- 服务端:接收到完整的请求后,在执行业务操作前,完成逻辑校验
- 格式校验
1.1.3 表单校验规则
- 长度:例如用户名长度,评论字符数量
- 非法字符:例如用户名组成
- 数据格式:例如Email格式、 IP地址格式
- 边界值:例如转账金额上限,年龄上下限
- 重复性:例如用户名是否重复
1.1.4 表单校验框架
-
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 :搭配hibernate-validator版本5...Final
tomcat8.5↑ :搭配hibernate-validator版本6...Final
1.2 快速使用
1. 开启校验
名称:@Valid 、 @Validated
类型:形参注解
位置:处理器类中的实体类类型的方法形参前方
作用:设定对当前实体类类型参数进行校验
范例:
@RequestMapping(value = "/addemployee")
public String addEmployee(@Valid Employee employee) {
System.out.println(employee);
}
2.设置校验规则
名称:@NotNull
类型:属性注解 等
位置:实体类属性上方
作用:设定当前属性校验规则
范例:
每个校验规则所携带的参数不同,根据校验规则进行相应的调整
具体的校验规则查看对应的校验框架进行获取
public class Employee{
@NotNull(message = "姓名不能为空")
private String name;//员工姓名
}
3.获取错误信息
@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接口将数据封装后传递到页面显示
页面获取后台封装的校验结果信息
1.3 多规则校验
- 同一个属性可以添加多个校验器
@NotNull(message = "请输入您的年龄")
@Max(value = 60,message = "年龄最大值不允许超过60岁")
@Min(value = 18,message = "年龄最小值不允许低于18岁")
private Integer age;//员工年龄
- 3种判定空校验器的区别
1.4 嵌套校验
名称:@Valid
类型:属性注解
位置:实体类中的引用类型属性上方
作用:设定当前应用类型属性中的属性开启校验
范例:
public class Employee {
//实体类中的引用类型通过标注@Valid注解,设定开启当前引用类型字段中的属性参与校验
@Valid
private Address address;
}
注意:开启嵌套校验后,被校验对象内部需要添加对应的校验规则
1.5 分组校验
- 同一个模块,根据执行的业务不同,需要校验的属性会有不同
- 新增用户
- 修改用户
- 对不同种类的属性进行分组,在校验时可以指定参与校验的字段所属的组类别
- 定义组(通用)
- 为属性设置所属组,可以设置多个
- 开启组校验
public interface GroupOne {
}
public String addEmployee(@Validated({GroupOne.class}) Employee employee){
}
@NotEmpty(message = "姓名不能为空",groups = {GroupOne.class})
private String name;//员工姓名
2 ssm整合
2.1 整合流程简介
整合步骤分析
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
2.2 项目结构搭建
Part0: 项目基础结构搭建
-
创建项目,组织项目结构,创建包
-
创建表与实体类
-
创建三层架构对应的模块、接口与实体类,建立关联关系
-
数据层接口(代理自动创建实现类)
- 业务层接口+业务层实现类
- 表现层类
public interface UserDao {
public boolean save(User user); public boolean update(User user);
public boolean delete(Integer uuid); public User get(Integer uuid);
public List<User> getAll(int page,int size);
public interface UserService {
public boolean save(User user); public boolean update(User user);
public boolean delete(Integer uuid);
public User get(Integer uuid);
public List<User> getAll(int page, int size);
/**
用户登录
@param userName 用户名
@param password 密码信息
@return
*/
public User login(String userName,String password);
}
Mybatis配置事务
<?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.itheima.dao.UserDao">
<!--添加-->
<insert id="save" parameterType="user">
insert into user(userName,password,realName,gender,birthday)values(#{userName},#{password},#{realName},#{gender},#{birthday})
</insert>
<!--删除-->
<delete id="delete" parameterType="int">
delete from user where uuid = #{uuid}
</delete>
<!--修改-->
<update id="update" parameterType="user">
update user set userName=#{userName},password=#{password},realName=#{realName},gender=#{gender},birthday=#{birthday} where uuid=#{uuid}
</update>
<!--查询单个-->
<select id="get" resultType="user" parameterType="int">
select * from user where uuid = #{uuid}
</select>
<!--分页查询-->
<select id="getAll" resultType="user">
select * from user
</select>
<!--登录-->
<select id="getByUserNameAndPassword" resultType="user" >
select * from user where userName=#{userName} and password=#{password}
</select>
</mapper>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--加载Spring配置文件到容器-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--监听器,监听ServletContext对象的创建和销毁的,当服务器启动项目被加载的时候,
ServletContext对象就会被创建,然后监听器就会触发,加载spring配置文件,
并且创建spring容器对象ApplicationContext,并且创建后该对象会放在ServletContext中-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--创建前端控制器 之前会创建Springmvc容器,然后从ServletContext域对象中获取Spring容器
然后判断是否为空,不为空将Spring的容器设置为自己的父容器-->
<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>
<!--过滤器-->
<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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
spirng-mvc
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--包扫描-->
<context:component-scan base-package="com.ybb.controller,com.ybb.interceptor"/>
<!--json格式转换-->
<mvc:annotation-driven/>
<!--配置完后静态和非静态访问进去-->
<mvc:default-servlet-handler/>
<!--配置拦截器-->
<!-- <mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/aaa/aa"/>
<bean class="com.ybb.Interceptors.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>-->
<!--文件上传-->
<!-- <bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"/>-->
</beans>
spring
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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/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">
<!--开启bean注解扫描-->
<context:component-scan base-package="com.ybb.service"/>
<!--加载properties文件-->
<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>
<!--mybatis的数据库工厂,同时配置分页插件-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.ybb.domain"/>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<prop key="helperDialect">mysql</prop>
<prop key="reasonable">true</prop>
</props>
</property>
</bean>
</array>
</property>
</bean>
<!--映射扫描-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ybb.dao"/>
</bean>
<!--事务管理器-->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven />
</beans>
junit
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class UserServiceTest {
@Autowired
private UserService userService;
@Test
public void testDelete(){
User user = new User(); userService.delete(3);
}
}
UserSerivceImpl
package com.ybb.service.Impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ybb.dao.UserDao;
import com.ybb.domain.User;
import com.ybb.service.UserService;
import com.ybb.system.exception.MyException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* Created by Administrator
* <p>
* Date :2020/8/12
* <p>
* Description :
* <p>
* Version :1.0
*/
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
public boolean save(User user) {
return userDao.save(user);
}
public boolean update(User user) {
return userDao.update(user);
}
public boolean delete(Integer uuid) {
return userDao.delete(uuid);
}
public User get(Integer uuid) {
return userDao.get(uuid);
}
public Page getAll(int page, int size) throws MyException {
PageHelper.startPage(page, size);
return (Page) userDao.getAll();
}
public User login(String userName, String password) {
return userDao.getByUserNameAndPassword(userName, password);
}
}
UserSerivce
package com.ybb.service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.ybb.domain.User;
import com.ybb.system.exception.MyException;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* Created by Administrator
* <p>
* Date :2020/8/12
* <p>
* Description :
* <p>
* Version :1.0
*/
public interface UserService {
//添加
public boolean save(User user);
//修改
public boolean update(User user);
//删除
public boolean delete(Integer uuid);
//查询单个
public User get(Integer uuid);
//查询全部用户信息
public Page getAll(int page, int size) throws MyException;
//根据用户名密码查询用户信息
public User login(String userName,String password);
}
Spring controller
package com.ybb.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.ybb.controller.results.Code;
import com.ybb.controller.results.Result;
import com.ybb.domain.User;
import com.ybb.service.UserService;
import com.ybb.system.exception.MyException;
import org.apache.ibatis.annotations.Insert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* Created by Administrator
* <p>
* Date :2020/8/12
* <p>
* Description :
* <p>
* Version :1.0
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public Result save(User user) {
boolean flag = userService.save(user);
return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERROR);
}
@PutMapping
public boolean update(User user) {
return userService.update(user);
}
@GetMapping("/{uuid}")
public Result get(@PathVariable Integer uuid) throws MyException {
if (uuid ==10){
throw new MyException("查询失败了。。。");
}
User user = userService.get(uuid);
return new Result(null != user ? Code.GET_OK : Code.GET_ERROR, user);
}
@DeleteMapping("/{uuid}")
public boolean delete(@PathVariable Integer uuid) {
return userService.delete(uuid);
}
@GetMapping("/{page}/{size}")
public Page getAll(@PathVariable Integer page, @PathVariable Integer size) throws MyException {
Page all = userService.getAll(page, size);
//System.out.println(all);
return all;
}
@PostMapping("/login")
public User login(String userName, String password) {
System.out.println(userName + " " + password);
User login = userService.login(userName, password);
return login;
}
}
拓展 表现层数据封装
表现层数据封装
- 前端接收表现层返回的数据种类
u操作是否成功 | true/false | 格式A |
---|---|---|
u单个数据 | 1,100,true | 格式B |
u对象数据 | json对象 | 格式C |
u集合数据 | json数组 | 格式D |
public class Result {
// 操作结果编码
private Integer code;
// 操作数据结果
private Object data;
// 消息
private String message;
public Result(Integer code) {
this.code = code;
}
public Result(Integer code, Object data) {
this.code = code;
this.data = data;
}
}
public class Code {
public static final Integer SAVE_OK = 20011;
public static final Integer SAVE_ERROR = 20010;
//其他编码
}
controller 调用
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public Result save(User user){
boolean flag = userService.save(user);
return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERROR);
}
@GetMapping("/{uuid}")
public Result get(@PathVariable Integer uuid){
User user = userService.get(uuid);
return new Result(null != user ?Code.GET_OK: Code.GET_ERROR,user);
}
}
自定义异常
自定义异常
-
设定自定义异常,封装程序执行过程中出现的问题,便于表现层进行统一的异常拦截并进行处理
- 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);
}
2.8 返回消息兼容异常信息
@Component
@ControllerAdvice
public class ProjectExceptionAdivce {
@ExceptionHandler(BusinessException.class)
@ResponseBody
//对出现异常的情况进行拦截,并将其处理成统一的页面数据结果格式
public Result doBusinessException(BusinessException e){
return new Result(e.getCode(),e.getMessage());
}
}
3 纯注解开发SSM
3.1 用注解替代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;
}
}
3.2 用注解替代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格式数据