《框架程序设计》期末复习

目录

Maven

简介

 工作机制(★)

依赖配置(★)

Maven命令

MyBatis 

入门

单参数查询(★)

多参数查询(★★★)

自定义映射关系(★★★)

基本增删改查操作(★)

Mapper接口定义(★★★)

注解方式配置SQL(★★★)

MyBatis动态SQL(★★★)

和标签

标签

标签

Spring

Spring框架介绍(★)

 Spring控制反转(★)

Spring依赖注入

基于XML方式依赖注入(★)

基于注解方式依赖注入(★★★)

1. 使用注解标记组件

2. 配置扫描组件所在包

Spring AOP面向切面编程

基于注解方式配置切面(★★★)

启用 AspectJ 自动代理功能

使用@Aspect 注解定义切面

使用@Pointcut 注解定义切点

使用注解定义通知

SpringMVC 

SpringMVC框架简介(★)

运行原理(★)

SpringMVC框架搭建

能够结合需求写出控制器代码(★★★)

@RequestMapping注解使用(★★★)

SpringMVC配置文件(★★★)

SpringMVC前后端数据交互(★★★)

基于JSON的数据交互(★)

拦截器

拦截器定义(★)

拦截器配置(★★★)

全局异常处理(★)

SSM整合

SSM框架整合配置(★★★)

Spring声明式事务管理(★★★)

基于XML实现

基于注解实现

事务失效场景

 


Maven

简介

Maven 的本质是⼀个项目管理工具,将项⽬开发和管理过程抽象成⼀个项目对象模型(POM),通过简单的配置和命令就可以完成项⽬的构建管理和依赖管理。 使⽤ Maven 可以实现⾃动化构建、测试、打包和发布项⽬,⼤⼤提⾼了开发效率和质量。 

 工作机制(★)

 

依赖配置(★)

通过Maven⼯程的pom.xml⽂件可以完成依赖配置。⽐如,我们需要在⼯程中使⽤MySQL驱动的Jar 包,我们只需要在pom.xml中完成添加如下依赖配置: 

<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>5.7.6</version>
</dependency>

groupId、artifactId和version是Jar包依赖的GAV三坐标,GAV三坐标就相当于人的姓+名,起到一个标识的作用。

在<dependency>节点中还有一个<scope>元素可以设置依赖的作用范围,有如下四个取值:

scope取值

编译阶段

测试阶段

运行阶段

compile(默认值)

有效

有效

有效

provided

有效

有效

无效

test

无效

有效

无效

runtime

无效

无效

有效

 默认值就是不写出这个元素的时候;再比如,一般导入junit依赖时,都是会标识test以表示只测试阶段。

Maven命令

Maven配置完成后,就可以使用Maven命令进行项目构建和依赖管理了。

命令

作用

说明

mvn -v

查看Maven当前版本信息

使用mvn –v或mvn –version命令,执行后的结果一样。

mvn clean

删除target目录

target目录是Maven的输出目录,主要存放生成的class、jar、war等文件。

mvn compile

编译程序

编译后的文件将存放在taget/classes目录中。

mvn package

打包项目

打包后的结果(jar或war包)将存放在target目录中。

mvn install

安装jar包到本地仓库

将打包好的jar包存放到Maven本地仓库中。

MyBatis 

入门

MyBatis是一个优秀的数据持久层框架,是一种半自动的ORM实现。MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code。随着开发团队转投Google Code旗下, iBatis3.x正式更名为MyBatis。 代码于2013年11月迁移到Github。

  • 目前比较流行的ORM框架有Hibernate和MyBatis。
  • 开发效率:Hibernate>Mybatis>JDBC
  • 运行效率:JDBC>Mybatis>Hibernate

单参数查询(★)

UserMapper.xml映射文件中添加如下SQL配置:

<!--根据用户名查询用户信息-->
<select id="selectUserByUsername" resultType="user">select * from t_user where username=#{username}
</select>

注:

  • id用来指定唯一标识resultType用来指定绑定结果类型
  • parameterType用来指定传递的参数类型,该属性也可以省略不写
  • #{ }就相当于JDBC中的问号占位符,用于接收调用者传递过来的一个参数。
  • 因为根据用户名查询用户信息只会传递一个参数,因此#{ }中的参数名可以任意
  • 使用${ }也可以接收参数,但是这种形式的传参在MyBatis底层进行的是字符串拼接的操作,可能会造成SQL注入的问题,实际开发中,能用#{}实现的,肯定不用${}。
  • 如果使用${}来接收参数,则是如下配置写法。
<!--根据用户名查询用户信息--><select id="selectUserByUsername" resultType="user">select * from t_user where username='${username}'</select>

多参数查询(★★★)

  • 能够根据题目要求写出对应的<select>配置

在UserMapper.xml中添加如下SQL配置:

    <!--根据性别和出生年份查询用户信息--><select id="selectUserByParam" resultType="user">select * from t_user where sex=#{sex} and year(birthDate)=#{birthYear}</select>

注:

  • 因为SQL配置需要接收两个参数,所以使用了两个#{}占位符
  • 对于多个参数,可以使用实体类或者Map来传递多个参数值
  • 要注意的是,#{}里的参数名一定要和实体类中的属性名或者Map中的键名一一对应,如果不一致将接收不到参数值。

自定义映射关系(★★★)

在SQL映射文件中,当查询结果列名和实体类属性名不一致时,可以使用<resultMap>标签实现自定义映射关系。

<resultMap id="employeeMap" type="Employee"><!-- 使用id标签设置主键列和主键属性之间的对应关系 --><!-- column属性用于指定字段名;property属性用于指定Java实体类属性名 --><id column="id" property="id"/><!-- 使用result标签设置普通字段和Java实体类属性之间的关系 --><result column="emp_name" property="empName"/><result column="emp_age" property="empAge"/><result column="emp_birth" property="empBirth"/><result column="emp_job" property="empJob"/><result column="emp_join" property="empJoin"/>
</resultMap>

注:

  • 通过<id>和<result>子标签可以定义数据库表字段和Java实体类属性之间的映射关系。
  • <id>用于定义主键列和主键属性之间的映射关系
  • <result>用于普通列和Java实体类属性之间的映射关系

映射关系定义完成后,我们还需要在SQL配置中使用resultMap属性引用该映射关系,MyBatis底层才能根据我们自定义的映射规则完成数据映射。

<!--SQL语句配置,将查询的结果映射到User对象中--><select id="selectAllEmployees" resultMap="employeeMap">select * from t_employee</select>

基本增删改查操作(★)

insert语句使用<insert>标签来配置,同样是使用#{}来接收参数,#{}里面的参数名要和实体类中的属性名一一对应,还要注意,对于<insert>、<update>和<delete>标签来说,不需要指定resultType属性,因为默认值为int类型,表示数据库受影响的行数

<!--新增一个用户-->
<insert id="insertOne">insert into t_user(username,password,age,sex,birthDate)values(#{username},#{password},#{age},#{sex},#{birthDate})
</insert>

Mapper接口定义(★★★)

  • 能够结合SQL配置写出正确的接口方法。

在MyBatis框架,接口的定义需要遵循如下的规范:

  • 方法名和SQL配置的id一致
  • 方法返回值和resultType一致
  • 方法的参数和SQL配置需要的参数一致

SQL配置:

    <!--根据性别和出生年份查询用户信息--><select id="selectUserByParam" resultType="user">select * from t_userwhere sex=#{sex} and year(birthDate)=#{birthYear}</select>

 SQL配置对应的接口方法:

List<User> selectUserByParam(UserParam param);

 注:因为在SQL配置中需要两个参数,这里接口方法的参数为实体类UserParam。

或者 

第二个SQL配置对应的接口方法: 

List<User> selectUserByParam(Map<String,Object> param);

注:这个接口是使用Map对象来传递多个参数。

或者

第二个SQL配置对应的接口方法:

List<User> selectUserByParam(@Param("sex") int sex, @Param("birthYear") String birthYear);

 注:通过接口的方式可以使用@Param注解传递多个简单类型参数。@Param中的参数名要和SQL配置中的参数名一一对应。

注解方式配置SQL(★★★)

  • 能够基于注解方式配置SQL语句。

MyBatis 提供了基于注解的方式来配置 SQL 语句。

  • @Insert注解:用于定义insert语句,作用等同于xml配置中<insert>标签
  • @Update注解:用于定义update语句,作用等同于xml配置中<update>标签
  • @Delete注解:用于定义delete语句,作用等同于xml配置中<delete>标签
  • @Select注解:用于定义select语句,作用等同于xml配置中<select>标签

MyBatis动态SQL(★★★)

<if>和<where>标签

  • <if>标签用于进行条件判断,类似于Java中的if语句,通过该标签可以有选择的加入SQL语句的片段。
  • <where>标签的作用是能够自动处理查询条件,智能的处理多余的where、and、or关键字
  • <if>和<where>标签组合可以实现动态条件查询
<select id="selectByParam" resultType="User">select * from t_user<!--自动处理多余的where,and,or关键字--><where><!--当username参数值不为空且不为空字符串时,则加入SQL片段--><if test="username!=null and username!=''">and username=#{username}</if><!--当sex参数值不为空时,则加入SQL片段--><if test="sex!=null">and sex=#{sex}</if><!--当birthYear参数值不为空时,则加入SQL片段--><if test="birthYear!=null and birthYear!=''">and year(birthDate)=#{birthYear}</if></where></select>

<trim>标签

<trim>标签是一个格式化的标记,主要用于动态拼接SQL的条件语句,可以完成set标签或者是where标签的功能。

<select id="selectByParam" resultType="User">select * from t_user<trim prefix="where" prefixOverrides="and|or"><!--当username参数值不为空且不为空字符串时,则加入SQL片段--><if test="username!=null and username!=''">and username=#{username}</if><!--当sex参数值不为空时,则加入SQL片段--><if test="sex!=null">and sex=#{sex}</if><!--当birthYear参数值不为空时,则加入SQL片段--><if test="birthYear!=null and birthYear!=''">and year(birthDate)=#{birthYear}</if></trim></select>

<foreach>标签

<foreach>标签可以在SQL配置中迭代集合类型参数。常用于构造in语句实现查询某一范围内的数据。可以用来实现批量查询、批量更新、批量删除和批量新增操作。 

<select id="selectListByNos" resultType="String">select stu_name from student<where><!--判断集合是否为空--><if test="list!=null and !list.isEmpty()">stu_no in<!--使用<foreach>遍历集合参数--><foreach collection="list"item="no"open="("close=")"separator=",">#{no}</foreach></if></where></select>
  • collection="list":指定要遍历的集合名称。
  • item="no":指定集合中每个元素的别名。
  • open="(":指定遍历开始时的前缀。
  • close=")":指定遍历结束时的后缀。
  • separator=",":指定集合中每个元素之间的分隔符。
  • #{no}:表示集合中的每个元素,用于生成SQL语句中的值。

Spring

Spring框架介绍(★)

Spring Framework(Spring框架)是一个开源的应用程序框架,由SpringSource公司开发,最初是为了解决企业级开发中各种常见问题而创建的。它提供了很多功能,例如:控制反转(IoC)、依赖注入(DI)、面向切面编程(AOP)、声明式事务管理(TX)等。其主要目标是使企业级应用程序的开发变得更加简单和快速,广泛应用于Java企业开发领域。

 Spring控制反转(★)

IoC(Inversion of Control)的含义是控制反转。 控制反转指的是当应用程序需要创建一个对象时,不再是应用程序直接通过new的方式创建该对象,而是由 Spring容器来创建和管理,即控制权由应用程序转移到 Spring容器中,也就是“反转”了控制权。

把UserDao对象注册到Spring容器中,我们可以在spring-beans.xml中加入如下<bean>配置:

 

<?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"><!--配置UserDao组件信息--><bean id="userDao" class="com.cg.dao.UserDao"></bean></beans>

从Spring容器中获取Bean并使用 

public class SpringTest {@Testpublic void test1(){//创建Ioc容器ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring-beans.xml");//从IoC容器中获取组件(根据name获取Bean)UserDao userDao=context.getBean("userDao",UserDao.class);//调用组件方法userDao.insert("张三",24);}
}

 在<bean>标签中,可以通过配置scope属性来定义Bean的作用域。

<!--通过scope属性定义Bean作用域-->
<bean id="..." class="..." scope="..."></bean>

scope常用可选值: 

取值

含义

创建对象的时机

默认值

singleton

在 IOC 容器中,这个 bean 的对象始终为单实例

IOC 容器初始化时

prototype

这个 bean 在 IOC 容器中有多个实例

获取 bean时

 

  • singleton是Spring中的默认作用域。当一个Bean的作用域被设置为singleton时,Spring容器只会创建该Bean的一个实例。无论多少个请求,都会返回同一个实例。
  • 适用于无状态的Bean,如工具类、服务类等。这些Bean不需要维护状态,每次调用方法时都是独立的。
  • prototype作用域的Bean,每次请求时都会创建一个新的实例。每次调用getBean方法时,都会返回一个新的Bean实例。
  • 适用于有状态的Bean,如用户会话管理、事务管理等。这些Bean需要维护状态,每次请求时都需要一个新的实例。

 

Spring依赖注入

Spring容器可以通过依赖注⼊(DI)功能将⼀个组件注册到另外⼀个组件的属性中,从⽽完成依赖关系的传递,解除对象之间的耦合,也可以称为属性注入。

基于XML方式依赖注入(★)

在 Spring容器 中,依赖注入(DI) 可以通过 XML 配置文件实现的。它提供了两种形式的依赖注入配置:Setter 方法注入和构造方法注入。

(1)Setter方法注入是指IoC容器可以动态调用Bean中属性的set方法,注入依赖对象。因此,基于Setter方法的依赖注入要求我们需要在Bean中为属性定义set方法。通过属性的set方法可以注入简单类型参数值或者其他Bean对象。在配置文件中使用<property>标签完成属性注入。

配置如下所示: 

<!--使用Bean标签配置Bean信息--><bean class="com.cg.bean.StudentBean"><!--使用property标签完成简单类型属性值的注入--><property name="name" value="张三"/><property name="code" value="0001"/></bean>

(2)构造方法注入是指IoC容器可以动态调用Bean的带参构造方法,注入依赖对象。因此,基于构造方法的依赖注入要求我们需要在Bean中定义带参构造方法,参数为要依赖的其他Bean对象引用或简单类型参数。在配置文件中使用使用<constructor-arg>标签完成参数注入。 

 

    <!--使用Bean标签配置Bean信息--><bean class="com.cg.bean.StudentBean"><!--使用constructor-arg标签完成构造方法参数的注入--><constructor-arg index="0" value="00001"/><constructor-arg index="1" value="李四"/></bean>

 

基于注解方式依赖注入(★★★)

基于注解方式的组件注册实现需要两个步骤:

  1. 使用注解标记组件
  2. 扫描组件所在的包
1. 使用注解标记组件

(1)Spring框架中提供了以下多个注解,这些注解可以直接标注在 Java 类上,将它们定义成 Spring Bean。

注解

说明

@Repository

常用于将数据访问层(Dao层)的组件标识为Spring中的Bean

@Service

常用于将业务逻辑层(Service层)的组件标识为Spring中的Bean

@Controller

常用于将控制层(Controller层)的组件标识为Spring中的Bean

@Component

常用于将除了以上三层以外的其他组件标识为Spring中的Bean

 

对于Spring使用IoC容器管理这些组件来说以上注解没有区别,可以互换, 只是习惯上不同的注解应用于不同层级的组件上, 让我们能够快速分辨组件的作用。

(2)通过使用 @Autowired 注解可以实现Spring容器中组件之间的依赖注入。

  • @Autowired 只需要标注在属性上面即可,并且不需要定义带参构造函数或者为属性定义set方法即可完成依赖注入。该注解默认根据类型装配,如果想根据名称装配,需要配合@Qualifier注解一起用。
@Service
public class UserService {@Autowiredprivate UserDao userDao;//省略其他代码
}

 

2. 配置扫描组件所在包

在spring-beans.xml中添加如下配置:

<!--扫描组件所在包-->
<context:component-scan base-package="com.cg.controller,com.cg.service,com.cg.dao"/>

 

Spring AOP面向切面编程

AOP(Aspect Oriented Programming),中文翻译为面向切面编程 ,是一种编程的思想,是对OOP( Object Oriented Programming,面向对象编程 )的补充和完善。 它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些与业务无关,但却影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。AOP可以减少系统的重复代码,降低模块之间的耦合度,并有利于提升项目的可操作性和可维护性。

基于注解方式配置切面(★★★)

启用 AspectJ 自动代理功能

Spring 基于注解配置 AOP 需要启用 AspectJ 自动代理功能,启用该功能后,Spring框架会自动扫描应用程序中所有被AOP注解标记的类,并自动创建AOP代理对象。

启用 AspectJ 自动代理功能需要在Spring的配置文件中添加如下配置:

<!--启用AspectJ自动代理功能-->
<aop:aspectj-autoproxy/>
使用@Aspect 注解定义切面

在 Spring 管理的 Bean 类上使用 @Aspect 注解就可以定义一个切面。

//日志记录切面类
@Aspect
public class LogAspect {}
使用@Pointcut 注解定义切点

在切面类中定义一个空方法并使用 @Pointcut 注解来定义切点,然后在@Pointcut注解中定义切点表达式用来匹配切入的目标类和方法。空方法的方法名就是切点的唯一标识id。

//日志记录切面类
@Aspect
public class LogAspect {//定义切点,切点的id为"pointcut()"@Pointcut("execution(* com.cg.service.*.*(..))")public void pointcut(){  }
}
  • @Pointcut注解中可以定义切点表达式,execution()表示切入的是方法。
  • * com.cg.service.*.*(..)表示切入com.cg.service包下的所有类的所有方法。

 

使用注解定义通知

在Spring AOP中通过以下注解来定义通知。

  • 使用 @Before 注解定义前置通知,在方法执行前添加操作。在该注解中,需要指定切点来控制当前通知方法要作用在哪些目标方法上。
//日志记录切面类
@Aspect
public class LogAspect {//定义切点,切点的id为"pointcut()"@Pointcut("execution(* com.cg.service.*.*(..))")public void pointcut(){}//前置通知方法@Before("pointcut()")public void before(){//方法调用之前打印日志System.out.println("开始调用方法");}
}
  • 使用 @AfterReturning 注解定义返回通知,在方法正常返回时执行,方法抛异常不执行。
    //返回通知方法@AfterReturning(value = "pointcut()")public void afterReturn(){System.out.println("结束调用方法");}

 

  • 使用 @After 注解定义后置通知,在方法退出时执行,无论方法内部是否抛出异常。

 

    //后置通知方法@After("pointcut()")public void after(){//方法调用之后打印日志System.out.println("结束调用方法");}
  • 使用 @AfterThrowing 注解定义异常通知,在方法抛出异常时执行。
    //异常通知方法@AfterThrowing("pointcut()")public void exception(){//方法调用异常打印日志System.out.println("调用方法出现异常");}

 

SpringMVC 

SpringMVC框架简介(★)

SpringMVC是Spring Web MVC的简称。Spring MVC属于SpringFrameWork的后续产品,是Spring框架基于MVC模式构建的用于Web应用程序开发的全功能模块。

运行原理(★)

SpringMVC框架是基于Servlet API构建的。在SpringMVC框架内部有一个核心Servlet “DispatcherServlet ”,DispatcherServlet继承于HttpServlet,在SpringMVC框架中用于做整体请求处理调度! 

 

SpringMVC框架搭建

能够结合需求写出控制器代码(★★★)

使用@Controller和@RequestMapping注解定义控制器。

@Controller
public class HelloController {@RequestMapping("/hello")public String hello(){return "hello";}
}

@RequestMapping注解使用(★★★)

@RequestMapping注解的作用就是将请求的 URL 地址控制器中的方法关联起来,建立映射关系。

  • 精准路径匹配: 在@RequestMapping注解指定 URL 地址时,按照请求地址进行精确匹配。

 

@Controller
public class HelloController {@RequestMapping("/hello")public String hello(){return "hello";}
}
  • 模糊路径匹配: 在@RequestMapping注解指定 URL 地址时, 通过使用通配符,匹配多个类似的地址。
  • 路径设置为/hello/*, /* 为单层任意字符串,/hello/a、/hello/aaa 可以访问此方法, /hello/a/a 不可以 。
@Controller
public class HelloController {@RequestMapping("/hello/*")public String hello(){return "hello";}
}

 

  • 路径设置为/hello/**, /** 为任意层任意字符串,/hello/a、/hello/aaa 可以访问此方法,/hello/a/a 也可以访问
@Controller
public class HelloController {@RequestMapping("/hello/**")public String hello(){return "hello";}
}
  • 在@RequestMapping中,通过value属性可以指定URL地址,通过method属性可以限定请求方式
@Controller
public class HelloController {@RequestMapping(value="/hello",method = RequestMethod.GET)public String hello(){return "hello";}
}

该方法只能接收get请求,如果违背请求方式,会报405异常。RequestMethod是一个枚举类型,定义了八种请求方式。 

 

public enum RequestMethod {GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
}

也可以使用@GetMapping、@PostMapping、@PutMapping、@DeleteMapping来限定请求方式。
 

 

@Controller
public class HelloController {@GetMapping("/hello")public String hello(){return "hello";}
}
  • 在@RequestMapping指定的URL地址中可以使用占位符{xxx}表示路径中的传递的值,再通过@PathVariable注解,将占位符所传递的值和控制器方法的形参进行绑定。
@Controller
public class HelloController {@RequestMapping("/hello/{username}")public String hello(@PathVariable("username")String username){System.out.println(username);return "hello";}
}
  • @RequestMapping也可以同时标注在类上,表示类中的所有方法都是以该地址作为父路径,访问类中方法时都需要在方法URL地址前面加上该父路径。
  • 访问该控制器里的方法都需要加上父级路径/abc,因此通过路径/abc/hello可以访问该hello方法。
@RestController
@RequestMapping("/abc")
public class HelloController {@RequestMapping("/hello")public String hello(){return "hello";}
}

SpringMVC配置文件(★★★)

  • 能够说出下面每一项配置的作用
<?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"><!--开启注解驱动--><mvc:annotation-driven/><!--扫描控制器所在的包,注册到IoC容器中--><context:component-scan base-package="com.cg.controller"/><!--配置视图解析器--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/views/"></property><property name="suffix" value=".jsp"></property></bean><!--静态资源访问映射路径,解决静态资源找不到的问题,也可以使用<mvc:default-servlet-handler/> --><mvc:resources location="/static/" mapping="/static/**"/>
</beans>
<?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"><!-- 配置DispatcherServlet --><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 加载类路径下的springmvc.xml(SpringMVC框架配置文件) --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><!-- 配置DispatcherServlet接受所有HTTP请求 --><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
</web-app>

SpringMVC前后端数据交互(★★★)

在HTTP请求中,无论是get请求还是post请求,一般都会携带参数,Controller接收参数的方式有以下三种:

  • HttpServletRequest接收
    @ResponseBody@RequestMapping("/doAdd")public String doAdd(HttpServletRequest request){String username= request.getParameter("username");String password= request.getParameter("password");String tel= request.getParameter("tel");int sex= Integer.parseInt(request.getParameter("sex"));User user=new User(username,password,tel,sex);userService.add(user);return "success";}
  • 方法形参接收
  • 在每一个形参前面都要加上@RequestParam注解指定接收的请求参数名称
    @ResponseBody@RequestMapping("/doAdd")public String doAdd(@RequestParam("username") String username,@RequestParam("password") String password,@RequestParam("tel") String tel,@RequestParam("sex") int sex){User user=new User(username,password,tel,sex);userService.add(user);return "success";}
  • 实体类型接收

我们直接使用User实体类就可以接收参数:

 

//用户实体类
@Data
public class User {private String username;//用户名private String password;//密码private String tel;//联系电话private int sex;//性别
}

 在Controller方法中加入User类型的参数,参数名任意。

    @ResponseBody@RequestMapping("/doAdd")public String doAdd(User user){userService.add(user);return "success";}

基于JSON的数据交互(★)

Spring MVC框架默认支持的 JSON 解析框架是 Jackson。Jackson 是一个用于处理 JSON 数据的 Java 库,它可以将 Java 对象序列化为 JSON 字符串,也可以将 JSON 字符串反序列化为 Java 对象。

在SpringMVC框架中使用Jackson需要以下四个步骤:

  1. 在SpringMVC项目中引入Jackson库依赖
  2. 在Spring容器中注册JSON消息转换器
<!--注解驱动,向容器中注入SpringMVC框架运行需要的组件Bean-->
<mvc:annotation-driven/>

 

3.在控制器方法中 使用 @RequestBody 注解来接收 JSON格式参数,并将其解析为 Java 对象

4.在控制器方法中 使用 @ResponseBody 注解将返回的Java对象转化为JSON数据放在响应体中

5.将实体类型作为控制器方法参数,并加上@RequestBody注解

 

@Controller
@RequestMapping("/api/product")
public class ProductController {@Autowiredprivate ProductService productService;@CrossOrigin@ResponseBody@RequestMapping("/add")public Result<Product> add(@RequestBody Product product){System.out.println(product.toString());productService.add(product);return new Result<Product>(1,"新增商品成功",product);}
}

 

拦截器

拦截器定义(★)

在SpringMVC项目中,可以通过实现HandlerInterceptor接口并重写接口中的方法来创建拦截器类

HandlerInterceptor接口中有三个方法,分别是preHandle、postHandle和afterCompletion方法。

  • preHandle方法是在控制器目标方法执行之前执行的方法
  • postHandle方法是在控制器目标方法执行之后执行的方法,目标方法内部异常时不执行
  • afterCompletion方法是在给与客户端最终响应之后执行的方法,无论目标方法内部是否异常都会执行。

拦截器配置(★★★)

拦截器类创建好之后,还需要通过在SpringMVC配置文件中配置<mvc:interceptors>标签完成拦截器的配置才能生效。

  • <mvc:interceptors>元素用于配置一组拦截器,其子元素<bean>定义的是全局拦截器,即拦截所有请求
    <!-- 配置拦截器 --><mvc:interceptors><!-- 配置一个全局拦截器,拦截所有客户端请求 --><bean class="interceptor.MyInterceptor"></bean></mvc:interceptors>

 

  • <mvc:interceptor>元素定义指定路径的拦截器,其子元素<mvc:mapping>用于配置拦截器作用的路径<mvc:exclude-mapping>用于配置拦截器不需要拦截,也就是放行的路径。
    <!-- 配置拦截器 --><mvc:interceptors><!-- 定义指定路径的拦截器 --><mvc:interceptor><!-- 配置拦截器拦截的路径 , /api/**表示拦截以/api/开头的所有请求 --><mvc:mapping path="/api/**"/><!-- 配置拦截器不需要拦截的路径 --><mvc:exclude-mapping path="/api/login"/><!-- 指定拦截器全限定类型--><bean class="interceptor.LoginInterceptor"></bean></mvc:interceptor></mvc:interceptors>

如果项目配置了了多个拦截器,那么拦截器的preHandle方法依次顺序执行,而拦截器的postHandle方法和afterCompletion反序执行

全局异常处理(★)

  • @ControllerAdvice@ExceptionHandler注解的组合可以实现捕获所有控制器抛出的异常并进行处理。

 

//全局异常处理器
@ControllerAdvice
public class GlobalExceptionHandler{@ResponseBody//处理业务异常@ExceptionHandler(BusinessException.class)public Result<Exception> handleBusException(BusinessException ex){return new Result<>(400,ex.getMessage(),ex);}@ResponseBody//处理系统异常@ExceptionHandler(Exception.class)public Result<Exception> handleException(Exception ex){return new Result<>(500,"抱歉,服务器出现了异常,正在加紧修复中",ex);}
}

SSM整合

SSM框架整合配置(★★★)

  • 需要在src/main/resources(类路径)下添加三个配置,分别是SpringMVC框架的配置(springmvc.xml)MyBatis核心配置文件(mybatis-config.xml)数据库连接的配置(db.properties)以及Spring和MyBatis框架的整合配置(spring-mybatis.xml)
  • 需要修改web.xml配置DispatcherServlet,同时加载src/main/resources(类路径)下的配置文件
  • 能够说出配置文件中每一项配置的作用。参考我之前的博客

 

Spring声明式事务管理(★★★)

Spring声明式事务管理通过AOP技术实现的事务管理,主要思想是将事务作为一个“切面”代码单独编写,然后通过AOP技术将事务管理的“切面”植入到业务目标类方法中。

Spring的声明式事务管理可以通过两种方式来实现,一种是基于XML的方式,另一种是基于注解的方式

基于XML实现

基于XML方式的声明式事务是在配置文件中通过<tx:advice>元素配置事务规则来实现的,然后通过使用<aop:config>编写的AOP配置,让Spring自动对目标生成代理。

<!--定义事务管理器 --><bean id="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--关联数据源--><property name="dataSource" ref="dataSource" /></bean><!-- 配置事务规则 --><tx:advice id="txAdvice" transaction-manager="txManager"><tx:attributes><!-- 定义哪些方法需要进行事务处理,*表示任意字符,比如find*表示以find开头的方法 --><tx:method name="find*" propagation="SUPPORTS" read-only="true"/><tx:method name="add*" propagation="REQUIRED"/><tx:method name="del*" propagation="REQUIRED"/><tx:method name="update*" propagation="REQUIRED"/><tx:method name="moneyTransfer" propagation="REQUIRED"/></tx:attributes></tx:advice><!-- 定义切面 --><aop:config><!-- 定义切点 --><aop:pointcut expression="execution(* com.cg.service.*.*(..))" id="pointcut"/><!-- 在指定的切点上应用事务规则 --><aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/></aop:config>

基于注解实现

  1. 开启事务注解驱动
    <!--定义事务管理器 --><bean id="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--关联数据源--><property name="dataSource" ref="dataSource" /></bean><!--开启事务注解驱动 --><tx:annotation-driven transaction-manager="txManager"/>
  1. 在需要事务管理的类或方法上使用@Transactional注解。
  • 如果将注解添加在Bean类上,则表示事务的设置对整个Bean类的所有方法都起作用;
  • 如果将注解添加在Bean类中的某个方法上,则表示事务的设置只对该方法有效。
  • 使用@Transactional注解时,可以通过参数配置具体事务规则

 

事务失效场景

  1. 失效场景1:使用try...catch...代码块捕获异常并处理,未抛出

原因分析:因为异常已经被捕获并处理,异常未抛出导致事务管理器未捕获到异常导致事务失效。

解决方案:去掉try...catch...代码块,或者将异常抛出去

  1. 失效场景2:抛出的异常不是RuntimeException异常及其子类。

原因分析:声明式异常处理默认只能捕获处理RuntimeException异常及其子类异常。对于其他类型的异常不会处理。

解决方案1:抛出异常时,异常类型要使用RuntimeException或者其子类,而不是Exception,特别是自定义的业务异常,一定要继承RuntimeException及其子类。

解决方案2:可以在@Transactional注解中通过配置rollbackFor属性指定异常类型为Exception,表示对所有异常都会出发事务管理机制。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 



 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/67934.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

于交错的路径间:分支结构与逻辑判断的思维协奏

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。* 这一节内容很多&#xff0c;文章字数达到了史无前例的一万一&#xff0c;我们要来学习分支与循环结构中…

计算机图形学【绘制立方体和正六边形】

工具介绍 OpenGL&#xff1a;一个跨语言的图形API&#xff0c;用于渲染2D和3D图形。它提供了绘制图形所需的底层功能。 GLUT&#xff1a;OpenGL的一个工具库&#xff0c;简化了窗口创建、输入处理和其他与图形环境相关的任务。 使用的函数 1. glClear(GL_COLOR_BUFFER_BIT |…

探秘block原理

01 概述 在iOS开发中&#xff0c;block大家用的都很熟悉了&#xff0c;是iOS开发中闭包的一种实现方式&#xff0c;可以对一段代码逻辑进行封装&#xff0c;使其可以像数据一样被传递、存储、调用&#xff0c;并且可以保存相关的上下文状态。 很多block原理性的文章都比较老&am…

vue3+ts+element-plus 对话框el-dialog设置圆角

对话框el-dialog设置圆角&#xff0c;实现的需求效果&#xff1a; 目前只能通过行内样式&#xff08;style"border-radius: 20px"&#xff09;来实现圆角效果&#xff1a;

机器学习算法(三):K近邻(k-nearest neighbors)

1 KNN的介绍和应用 1.1 KNN的介绍 kNN(k-nearest neighbors)&#xff0c;中文翻译K近邻。我们常常听到一个故事&#xff1a;如果要了解一个人的经济水平&#xff0c;只需要知道他最好的5个朋友的经济能力&#xff0c; 对他的这五个人的经济水平求平均就是这个人的经济水平。这…

大语言模型兵马未动,数据准备粮草先行

​从OpenAI正式发布ChatGPT开始&#xff0c;大型语言模型&#xff08;LLM&#xff09;就变得风靡一时。对业界和吃瓜群众来说&#xff0c;这种技术最大的吸引力来自于理解、解释和生成人类语言的能力&#xff0c;毕竟这曾被认为是人类独有的技能。类似CoPilot这样的工具正在迅速…

Network Compression(李宏毅)机器学习 2023 Spring HW13 (Boss Baseline)

1. Introduction to Network Compression 深度学习中的网络压缩是指在保持神经网络性能的同时,减少其规模的过程。这非常重要,因为深度学习模型,尤其是用于自然语言处理或计算机视觉的大型模型,训练和部署的计算成本可能非常高。网络压缩通过降低内存占用并加快推理速度,…

UnityDots学习(二)

在一里已经概述了什么是Dots&#xff0c;已经如果使用它&#xff0c;我们要做的思维转变。 简单总结下&#xff1a; Dots使用了计算器多核&#xff0c;已经3级缓存的优势&#xff0c;在此基础上使用Brust编译器对各个平台实现了代码优化。从而达到了加速提升的效果。 我们要…

Linux (CentOS) 安装 Docker 和 Docker Compose

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode︱ Gitee ︱ Github &#x1f496; 欢迎点赞 &#x1f44d; 收藏 ⭐评论 …

c++ 预备

目录 前言 一&#xff0c;知识点的补充 二&#xff0c;c语言与c 三&#xff0c;面向对象的三大特点 前言 将进入c的学习&#xff0c;接下来是对于c的预备和c的一些预习 一&#xff0c;知识点的补充 1 标识符 标识符不能为关键字 标识符只能由下划线&#xff0c;数字&#xf…

SpringBoot项目实战(41)--Beetl网页使用自定义函数获取新闻列表

在Beetl页面中可以使用自定义的函数从后台新闻列表中获取新闻数据展示到页面上。例如我们可以从后台新闻表中获取新闻按照下面的格式展示&#xff1a; <li><a href"#">东亚非遗展即将盛妆亮相 揭起盖头先睹为快</a></li><li><a hre…

从零开始开发纯血鸿蒙应用之多签名证书管理

从零开始开发纯血鸿蒙应用 一、前言二、鸿蒙应用配置签名证书的方式1、自动获取签名证书2、手动配置签名证书 三、多签名证书配置和使用四、多证书使用 一、前言 由于手机操作系统&#xff0c;比电脑操作系统脆弱很多&#xff0c;同时&#xff0c;由于手机的便携性&#xff0c…

数据结构初阶---排序

一、排序相关概念与运用 1.排序相关概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的…

系统看门狗配置--以ubuntu为例

linux系统配置看门狗 以 ubuntu 系统配置看门狗为例 配置看门狗使用的脚本文件&#xff0c;需要使用管理员权限来执行&#xff1a; 配置是&#xff1a;系统每 30S 喂一次狗&#xff0c;超过 60S 不进行投喂&#xff0c;就会自动重启。 1. 系统脚本内容&#xff1a; #!/bin/b…

opencv的NLM去噪算法

NLM&#xff08;Non-Local Means&#xff09;去噪算法是一种基于图像块&#xff08;patch&#xff09;相似性的去噪方法。其基本原理是&#xff1a; 图像块相似性&#xff1a;算法首先定义了一个搜索窗口&#xff08;search window&#xff09;&#xff0c;然后在该窗口内寻找…

Docker运维高级容器技术知识点总结

1、虚拟机部署和容器化部署的区别是什么&#xff1f; 1、技术基础&#xff1a; <1>.虚拟化技术在物理硬件上创建虚拟机&#xff0c;每台虚拟机运行自己完整的操作系统、从而实现资源隔离。 <2>.容器化技术&#xff1a;将应用程序打包在容器内&#xff0c;在进程空间…

双模充电桩发展前景:解锁新能源汽车未来的金钥匙,市场潜力无限

随着全球能源转型的浪潮席卷而来&#xff0c;新能源汽车行业正以前所未有的速度蓬勃发展&#xff0c;而作为其坚实后盾的充电基础设施&#xff0c;特别是双模充电桩&#xff0c;正逐渐成为推动这一变革的关键力量。本文将从多维度深入剖析双模充电桩的市场现状、显著优势、驱动…

python3GUI--大屏可视化-传染病督导平台 By:PyQt5

文章目录 一&#xff0e;前言二&#xff0e;预览三&#xff0e;软件组成&开发心得1.样式&使用方法2.左侧表格实现3.设计4.学习5.体验效果 四&#xff0e;代码分享1.环形渐变进度组件2.自定义图片的背景组件 五&#xff0e;总结 大小&#xff1a;60.9 M&#xff0c;软件…

某漫画网站JS逆向反混淆流程分析

文章目录 1. 写在前面1. 接口分析2. 反混淆分析 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Pyth…

ffmpeg aac s16 encode_audio.c

用ffmpeg库时&#xff0c;用代码对pcm内容采用aac编码进行压缩&#xff0c;出现如下错误。 [aac 000002bc5edc6e40] Format aac detected only with low score of 1, misdetection possible! [aac 000002bc5edc8140] Error decoding AAC frame header. [aac 000002bc5edc81…