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

目录

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_user
        where 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 {
    @Test
    public 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 {
    @Autowired
    private 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 {
    @Autowired
    private 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,表示对所有异常都会出发事务管理机制。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 



 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

51单片机——I2C-EEPROM

I2C&#xff1a;总线标准或通信协议 EEPROM&#xff1a;AT24C02芯片 开发板板载了1个EEPROM模块&#xff0c;可实现IIC通信 1、EEPROM模块电路&#xff08;AT24C02&#xff09; 芯片的SCL和SDA管脚是连接在单片机的P2.1和P2.0上 2、I2C介绍 I2C&#xff08;Inter&#xff…

了解npm:JavaScript包管理工具

在JavaScript的生态系统中&#xff0c;npm&#xff08;Node Package Manager&#xff09;无疑是一个举足轻重的存在。它不仅是Node.js的包管理器&#xff0c;更是前端开发不可或缺的一部分&#xff0c;为开发者提供了丰富的包资源、便捷的包管理以及强大的社区支持。本文将深入…

Vscode辅助编码AI神器continue插件

案例效果 1、安装或者更新vscode 有些版本的vscode不支持continue,最好更新到最新版,也可以直接官网下载 https://code.visualstudio.com/Download 2、安装continue插件 搜索continue,还未安装的,右下脚有个Install,点击安装即可 <

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…

what?ngify 比 axios 更好用,更强大?

文章目录 前言一、什么是ngify&#xff1f;二、npm安装三、发起请求3.1 获取 JSON 数据3.2 获取其他类型的数据3.3 改变服务器状态3.4 设置 URL 参数3.5 设置请求标头3.6 与服务器响应事件交互3.7 接收原始进度事件3.8 处理请求失败3.9 Http Observables 四、更换 HTTP 请求实现…

论文笔记(六十一)Implicit Behavioral Cloning

Implicit Behavioral Cloning 文章概括摘要1 引言2 背景&#xff1a;隐式模型的训练与推理3 隐式模型与显式模型的有趣属性4 policy学习成果5 理论见解&#xff1a;隐式模型的通用逼近性6 相关工作7 结论 文章概括 引用&#xff1a; inproceedings{florence2022implicit,titl…

CES 2025|美格智能高算力AI模组助力“通天晓”人形机器人震撼发布

当地时间1月7日&#xff0c;2025年国际消费电子展&#xff08;CES 2025&#xff09;在美国拉斯维加斯正式开幕。美格智能合作伙伴阿加犀联合高通在展会上面向全球重磅发布人形机器人原型机——通天晓&#xff08;Ultra Magnus&#xff09;。该人形机器人内置美格智能基于高通QC…

【安卓开发】自定义应用图标

要在 Android Studio 中设置应用的图标并自定义大小&#xff0c;可以使用 Android Studio 提供的图标生成工具。以下是具体步骤&#xff1a; 1、打开图标生成工具&#xff1a; 在 Android Studio 中&#xff0c;右键点击 res 文件夹&#xff0c;选择 New -> Image Asset。 …

django基于Python的电影推荐系统

Django 基于 Python 的电影推荐系统 一、系统概述 Django 基于 Python 的电影推荐系统是一款利用 Django 框架开发的智能化应用程序&#xff0c;旨在为电影爱好者提供个性化的电影推荐服务。该系统通过收集和分析用户的观影历史、评分数据、电影的属性信息&#xff08;如类型…

C++笔记之数据单位与C语言变量类型和范围

C++笔记之数据单位与C语言变量类型和范围 code review! 文章目录 C++笔记之数据单位与C语言变量类型和范围一、数据单位1. 数据单位表:按单位的递增顺序排列2. 关于换算关系的说明3. 一般用法及注意事项4. 扩展内容5. 理解和使用建议二、C 语言变量类型和范围基本数据类型标准…

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

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

OCR文字识别—基于PP-OCR模型实现ONNX C++推理部署

概述 PaddleOCR 是一款基于 PaddlePaddle 深度学习平台的开源 OCR 工具。PP-OCR是PaddleOCR自研的实用的超轻量OCR系统。它是一个两阶段的OCR系统&#xff0c;其中文本检测算法选用DB&#xff0c;文本识别算法选用CRNN&#xff0c;并在检测和识别模块之间添加文本方向分类器&a…

webpack03

什么是source-map 将代码编译压缩之后&#xff0c;&#xff0c;可以通过source-map映射会原来的代码&#xff0c;&#xff0c;&#xff0c;在调试的时候可以准确找到原代码报错位置&#xff0c;&#xff0c;&#xff0c;进行修改 source-map有很多值&#xff1a; eval &#…

H266/VVC 帧内预测中 ISP 技术

帧内子划分 ISP ISP 技术是在 JVET-2002-v3 提案中详细介绍其原理&#xff0c;在 VTM8 中完整展示算法。ISP是线基内预测&#xff08;LIP&#xff09;模式的更新版本&#xff0c;它改善了原始方法在编码增益和复杂度之间的权衡&#xff0c;ISP 算法的核心原理就是利用较近的像…

day05_Spark SQL

文章目录 day05_Spark SQL课程笔记一、今日课程内容二、Spark SQL 基本介绍&#xff08;了解&#xff09;1、什么是Spark SQL**为什么 Spark SQL 是“SQL与大数据之间的桥梁”&#xff1f;****实际意义**为什么要学习Spark SQL呢?**为什么 Spark SQL 像“瑞士军刀”&#xff1…

Win11+WLS Ubuntu 鸿蒙开发环境搭建(二)

参考文章 penHarmony南向开发笔记&#xff08;一&#xff09;开发环境搭建 OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——标准系统移植指南&#xff08;一&#xff09; OpenHarmony&#xff08;鸿蒙南向开发&#xff09;——小型系统芯片移植指南&#xff08;二&…

【杂谈】-50+个生成式人工智能面试问题(四)

7、生成式AI面试问题与微调相关 Q23. LLMs中的微调是什么&#xff1f; 答案&#xff1a;虽然预训练语言模型非常强大&#xff0c;但它们并不是任何特定任务的专家。它们可能对语言有惊人的理解能力&#xff0c;但仍需要一些LLMs微调过程&#xff0c;开发者通过这个过程提升它…

【深度学习】数据预处理

为了能用深度学习来解决现实世界的问题&#xff0c;我们经常从预处理原始数据开始&#xff0c; 而不是从那些准备好的张量格式数据开始。 在Python中常用的数据分析工具中&#xff0c;我们通常使用pandas软件包。 像庞大的Python生态系统中的许多其他扩展包一样&#xff0c;pan…

赛灵思(Xilinx)公司Artix-7系列FPGA

苦难从不值得歌颂&#xff0c;在苦难中萃取的坚韧才值得珍视&#xff1b; 痛苦同样不必美化&#xff0c;从痛苦中开掘出希望才是壮举。 没有人是绝对意义的主角&#xff0c; 但每个人又都是自己生活剧本里的英雄。滑雪&#xff0c;是姿态优雅的“贴地飞行”&#xff0c;也有着成…

城市生命线安全综合监管平台

【落地产品&#xff0c;有需要可留言联系&#xff0c;支持项目合作或源码合作】 一、建设背景 以关于城市安全的重要论述为建设纲要&#xff0c;聚焦城市安全重点领域&#xff0c;围绕燃气爆炸、城市内涝、地下管线交互风险、第三方施工破坏、供水爆管、桥梁坍塌、道路塌陷七…