SSM框架

SSM框架学习第三天

SSM框架学习第一天
SSM框架学习第二天

Spring事务

事务作用:在数据层保障一系列的数据库操作同成功或同失败

Spring事务:在数据层和业务层保障了一系列的数据库操作同成功同失败

Spring事务实现:

Spring提供了PlatformTransactionManager接口,实现Spring事务的实现。

image-20220710111526114

Spring还提供了一个DataSourceTransactionManager实现类,但是这个实现类的内部实现是用JDBC的,只有用JDBC才能用这个实现类来实现事务。

image-20220710111839128

案例

模拟银行转账

image-20220710223026896
用事务实现同成功或者同失败。

实现:

dao层代码

package com.lwg.dao;

import com.lwg.pojo.Deposit;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;

@Repository
public interface DepositDao {
    @Update("UPDATE deposit SET balance=balance+100.0 WHERE id=#{id}")
    public int addMoney(@Param("id") int id, @Param("money") double money);
    @Update("UPDATE deposit SET balance=balance-#{money} WHERE id=#{id}")
    public int reduceMoney(@Param("id") int id, @Param("money") double money);
    @Insert("INSERT INTO deposit(NAME,balance) VALUES(#{name},#{balance})")
    public int addUser(Deposit deposit);
}

(1)开启事务,关键词@Transactional

service层代码

package com.lwg.service;

import com.lwg.dao.DepositDao;

import com.lwg.pojo.Deposit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.Transient;

@Service
public class DepositService {
    @Autowired
    private DepositDao depositDao;
    @Transactional   //开启事务
    public void transfer(int outId,int inId,double money){
        System.out.println(money);
        int i=depositDao.addMoney(inId,money);
        System.out.println(i);
        int g=1/0;  //会报错,从而导致前面的操作成功,后面操作失败
        int i1 = depositDao.reduceMoney(outId, money);
        System.out.println(i1);
    }
    public void addDeposit(Deposit deposit){
        int i = depositDao.addUser(deposit);
        System.out.println(deposit);
        System.out.println(i);
    }
}

(2)定义事务

创建Bean交由spring管理。

在jdbc配置类中配置Bean

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
    DataSourceTransactionManager transactionManager=new DataSourceTransactionManager();
    transactionManager.setDataSource(dataSource);
    return transactionManager;
}

(3)在spring配置类中定义使用注解方式使用事务

spring配置类代码

package com.lwg.config;

import org.springframework.context.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@ComponentScan("com.lwg")
@PropertySource("jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
@EnableTransactionManagement  //注解方式使用事务
public class SpringConfig {

}

Spring事务角色

image-20220710225037389

Spring事务相关配置

image-20220710225327477

以上属性都可以用注解方式进行配置

格式:

@Transactional(readOnly = true,timeout = -1) 

**事务传播行为:**事务协调员对事务管理员所携带事务的处理态度,通俗讲就是我的事务加不加入你开的事务里,是否和你同一个事务,也就是是否和你同成功或者同失败。

实现事务传播行为

@Transactional(propagation = Propagation.REQUIRES_NEW) //事务传播行为,我自己一个事务,不和你同一个事务

propagation属性值:

image-20220710231816611

案例:

image-20220710231121059

使用事务传播行为实现需求

代码实现:

准备日志表和日志实体类

日志表sql语句:

CREATE TABLE `user_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `info` text,
  `create_date` char(16) DEFAULT NULL,
  `result` char(1) DEFAULT NULL COMMENT '0成功,1失败',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8

日志实体类:

package com.lwg.pojo;

import com.lwg.config.SpringConfig;

public class UserLog {
    private int id ;
    private String info;
    private String createDate;
    private String result;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public String getCreateDate() {
        return createDate;
    }

    public void setCreateDate(String createDate) {
        this.createDate = createDate;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    @Override
    public String toString() {
        return "UserLog{" +
                "id=" + id +
                ", info='" + info + '\'' +
                ", createDate='" + createDate + '\'' +
                ", result='" + result + '\'' +
                '}';
    }
}

dao层:

package com.lwg.dao;

import com.lwg.pojo.UserLog;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Results;
import org.springframework.stereotype.Repository;

@Repository
public interface LogDao {
    @Insert("INSERT  INTO user_log(id,info,create_date,result) VALUES(#{id},#{info},#{createDate},#{result})")
    @Results(id="logMap",value = {
            @Result(property ="createDate",column ="create_date")
    })
    public int insertLog(UserLog userLog);
}

service层

package com.lwg.service;

import com.lwg.dao.LogDao;
import com.lwg.pojo.UserLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class LogService {
    @Autowired
    private LogDao logDao;
    @Transactional(propagation = Propagation.REQUIRES_NEW) //事务传播行为,我自己一个事务,不和你同一个事务
    public int addLog(UserLog userLog){
        return logDao.insertLog(userLog);
    };
}

修改上面那个转账案例的service层

package com.lwg.service;

import com.lwg.dao.DepositDao;

import com.lwg.pojo.Deposit;
import com.lwg.pojo.UserLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.beans.Transient;
import java.text.SimpleDateFormat;
import java.util.Date;

@Service
public class DepositService {
    @Autowired
    private DepositDao depositDao;
    @Autowired
    private LogService logService;
    @Transactional(timeout = -1)   //开启事务
    public void transfer(int outId,int inId,double money){
        String retlut="1";
        try {
            System.out.println(money);
            int i=depositDao.addMoney(inId,money);
            System.out.println(i);
//            int g=1/0;
            int i1 = depositDao.reduceMoney(outId, money);
            System.out.println(i1);
            retlut="0";
        }finally {
            Deposit inDeposit = selectById(inId);
            Deposit outDeposit = selectById(outId);
            String inName = inDeposit.getName();
            String outName = outDeposit.getName();
            System.out.println(outName);
            System.out.println(inName);
            String info=outName+"向"+inName+"转账"+money+"元";
            System.out.println(info);
            System.out.println(retlut);
            SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm");
            String newDate = sdf.format(new Date());
            UserLog userLog=new UserLog();
            userLog.setCreateDate(newDate);
            userLog.setInfo(info);
            userLog.setResult(retlut);
            logService.addLog(userLog);
        }

    }
    public void addDeposit(Deposit deposit){
        int i = depositDao.addUser(deposit);
        System.out.println(deposit);
        System.out.println(i);
    }
    public Deposit selectById(int id){
        return depositDao.selectById(id);
    }
}

SpringMVC

简介

SpringMVC是一种基于Java实现MVC模型的轻量级web框架

SpringMVC是Spring的一部分,SpringMVC和JavaWeb中的Servlet技术功能等同,用于web层开发,优点就是相同功能SpringMVC用更少的代码。

入门案例

(1)导包

导servlet、springMVC

<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>3.1.0</version>
  <scope>provided</scope>
</dependency>


<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.2.10.RELEASE</version>
</dependency>

(2)定义一个表现层Bean

@Controller 表现层Bean注解

package com.lwg.controller;

import org.apache.ibatis.annotations.Results;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class Demo1Controller {
    @RequestMapping("/demo1")  //请求路径
    @ResponseBody
    public String demo1(){
        System.out.println("user SpringMVC");
        return "{msg:user SpringMVC}";  //返回请求
    }
}

(3)初始化SpringMVC,实现SpringMVC配置类,设定SpringMVC加载Bean对应的路径

package com.lwg.config;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;

@Configuration
@ComponentScan("com.lwg.controller")
@EnableWebMvc  //开启json数据转换成对象的功能
public class SpringMvcConfig {
}

(4)定义一个servlet容器启动配置类,初始化servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求

package com.lwg.config;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

public class ServletContinerslnerslnitConfig extends AbstractDispatcherServletInitializer {
   //加载SpringMVC容器配置
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext acx=new AnnotationConfigWebApplicationContext();
        acx.register(SpringMvcConfig.class);
        return acx;
    }
    //设置哪些请求归SpringMVC处理
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"}; //所有请求
    }
//    加载spring容器配置
    @Override
    protected WebApplicationContext createRootApplicationContext() {
         AnnotationConfigWebApplicationContext acx=new AnnotationConfigWebApplicationContext();
        acx.register(SpringConfig.class);
        return acx;
    }
}

运行结果:

image-20220713115249290

在spring配置类加载Bean时如何限制不加载springMVC加载的Bean

第一种方法,我加载的路径下包含了SpringMVC加载的Bean,去掉SpringMVC加载的Bena。

//@ComponentScan("com.lwg")
@ComponentScan(
        value = "com.lwg",
        //排除指定注解方式的Bean
        excludeFilters =@ComponentScan.Filter(
                type = FilterType.ANNOTATION,
                classes = Controller.class
        )
)

第二种方式,精准加载,spring加载Bean写精准路径。

@ComponentScan({"com.lwg.dao","com.lwg.service"})

简化第四步的Servlet容器类的配置信息

package com.lwg.config;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

/*public class ServletContinerslnerslnitConfig extends AbstractDispatcherServletInitializer {
   //加载SpringMVC容器配置
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext acx=new AnnotationConfigWebApplicationContext();
        acx.register(SpringMvcConfig.class);
        return acx;
    }
    //设置哪些请求归SpringMVC处理
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"}; //所有请求
    }
//    加载spring容器配置
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext acx=new AnnotationConfigWebApplicationContext();
        acx.register(SpringConfig.class);
        return acx;
    }
}*/
//简化
public class ServletContinerslnerslnitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}
请求与响应
请求映射路径

image-20220713160725416

接收参数

普通参数的获取

定义方法的形参类型和名字和参数的类型名字一致即可。无论是get还是post请求都是这个方法获取参数。

例:获取参数为name、ager.
image-20220713161642554

处理获取参数中文乱码

添加过滤器,在servlet容器类中添加

//添加过滤器
@Override
protected Filter[] getServletFilters() {
    CharacterEncodingFilter filter=new CharacterEncodingFilter();  //编码格式过滤器类
    filter.setEncoding("UTF-8");  //设置编码格式
    return new Filter[]{filter};
}

当形参名与请求传过来的参数名不一致时,上面是获取不到的,可用@RequestParam注明参数名

image-20220713163906473

形参名直接用实体类aojo类对象,当请求传进来的参数名与对象属性名一致会自动封装进对象。

image-20220713164719513

当参数有多个值时,比如复选框,形参为数组即可接收到参数。

image-20220713165154119

也可以集合获取

image-20220713165834922

接收json数据

(1)jons数据为集合

传的json数据:

image-20220713171229665

获取参数要用@RequestBody
image-20220713171316444

(2)json数据为pojo对象,是对象类型

传的josn数据
image-20220713171743924

使用关键词@RequestBody,传的Json数据字段名和对象属性名一致就会自动封装在对象里。
image-20220713171822192

(3)json数据是对象数组

传的josn数据

image-20220713174506009

使用关键词@RequestBody

image-20220713174556600

日期参数接收,可以直接使用Data类的对象接收,会自动转换,日期格式有默认格式,当格式不一致要使用关键词@DateTimeFormat(pattern = “日期格式”),默认格式是yyyy/MM/dd

y:年 M:月 d:日 H:小时 m:分 s:秒
image-20220713175535082

响应

(1)响应页面,即响应跳转页面

直接返回页面路径即可

image-20220713221900991

(2)返回文本数据,要使用@ResponseBody注解
image-20220713222243276

(3)返回json格式数据

直接返回返回的数据就可以了,无论是数组、还是pojo对象,还是列表,会自动转成json数据返回。

REST风格

描述访问资源的形式

这种形式称为RESTful,这种开发风格称为REST风格

image-20220713223814842
image-20220713223857003

入门案例

package com.lwg.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class UserController {
    //查询所有
    @RequestMapping(value = "/users",method = RequestMethod.GET)
    @ResponseBody
    public String allData(){
        System.out.println("查询所有,使用get请求,不带路径参数");
        return "all";
    }
    //查询单个
    @RequestMapping(value = "users/{id}",method = RequestMethod.GET)
    @ResponseBody
    //使用@PathVariable指明这是路径参数,参数写在路径上,不是带?的那种
    public String selectOne(@PathVariable Integer id){
        System.out.println("查询id为"+id+"的数据");
        return "one";
    }
    //修改
    @RequestMapping(value = "users/{id}",method = RequestMethod.PUT)
    @ResponseBody
    public String updata(@PathVariable Integer id){
        System.out.println("修改id"+id+"的数据");
        return "updata";
    }
    //保存新增
    @RequestMapping(value = "users",method = RequestMethod.POST)
    @ResponseBody
    public String sava(){
        System.out.println("新增保存");
        return "save";
    }
    //删除
    @RequestMapping(value = "users/{id}",method = RequestMethod.DELETE)
    @ResponseBody
    public String delelet(@PathVariable Integer id){
        System.out.println("删除id为"+id);
        return "delete";
    }
}

使用@PathVariable注明路径参数,形参名要与 @RequestMapping路径上写的一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

广深度优先

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值