南宁实训02springmvc

依赖注解DI的实现方式

在这里插入图片描述

  • (1)给成员变量赋值的方式有两种
  • (2)1是有参构造方法
  • (3)2是先通过无参构造方法创建对象,再调用set方法
  • (4)依赖注入 简写DI 本质是 对成员变量赋值
  • (5)可以使用xml配置也可以使用注解配置
  • (6)xml可以使用constructor-arg标签,或property标签

public class ProductService implements IProductService{
    //private IProductDao productDao = new ProductDao();//多态
    
    private IProductDao productDao;
    //构造方法
    public ProductService(IProductDao productDao) {
        this.productDao = productDao;
    }
    //无参构造方法


    public ProductService() {
    }

    public void setProductDao(IProductDao productDao) {
        this.productDao = productDao;
    }

先用xml配置

<bean id="productDao" class="com.huawei.dao.ProductDao"></bean>
     <bean id="productService" class="com.huawei.service.ProductService">
         <constructor-arg name="productDao" ref="productDao"/>
     </bean>

     <bean id="productService2" class="com.huawei.service.ProductService">
         <property name="productDao" ref="productDao"/>
     </bean>

也可以使用注解配置

 <!-- 扫描指定的目标,只要有@Service,@Repository @Controller @Component-->
    <context:component-scan base-package="com.huawei"/>
@Service
public class ProductService implements IProductService{
    //private IProductDao productDao = new ProductDao();//多态
    @Autowired
    private IProductDao productDao;
@Repository
public class ProductDao

在这里插入图片描述

依赖注解DI的配置数据源与JdbcTemplate

  • (1)如果是调用别人定义的类,不能加注解的情况下,只能使用xml
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"
          id="dataSource">
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/db_product"/>
    </bean>

    <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

批量操作的事务问题

  • (1)事务:一组操作要么全部成功,如果有一条失败就得回滚
  • (2)事力处理一般需要在业务层编写事务代码

 @Test
    public void test01(){
        //业务层需要处理事务,需要使用AOP
        //事务:一组操作要么全部成功,如果有一条失败就得回滚
        //转钱  -500 + 500
        IProductService iProductService = (IProductService) context.getBean("productService");
        iProductService.deleteProducts("1","2","3");
    }

在ProductSerivice中

public void deleteProducts(String... ids) {
        if (ids.length == 0){
            return;
        }
        for (int i = 0; i < ids.length; i++) {
            //模拟,删到第2条就抛出异常
            if(i == 1){
                System.out.println(1/0);
            }
            productDao.deleteById(ids[i]);
        }
    }

执行测试发现,第一条删除成功,第二条起失败,
但是数据没有回滚,原因是没有编写事务处理代码

静态代理添加事务代码

  • (1)在不改变源代码的基础上对目标方法进行增强,有两种方式
  • (2)1,是静态代码
  • (3)2,是动态代理,又分JDK动态代理,CGlib动态代理
  • (4)Spring AOP使用两种动态代理
  • (5)静态代理,由开发者自己编写代理类,要求代理类实现与目标相同的接口,内部还是调用目标对象与增强对象
public class AccountDao {
    public void update(double money){
        System.out.println("update ..."+money);
    }
}

public class MyTxManager {
    public void begin(){
        System.out.println("开启事务");
    }
    public void commit(){
        System.out.println("提交事务");
    }
    public void rollback(){
        System.out.println("回滚事务");
    }
    public void close(){
        System.out.println("关闭事务");
    }
}

//静态代理模式
//代理就是生成一个新类
//静态代理,由你来生成这个类
//实现相同的接口
//静态代理,比直接 改代码安全,但是方法多的话,工作量比较大
public class AccountServiceNew implements IAccountService{
    private AccountService accountService=new AccountService();
    private MyTxManager txManager=new MyTxManager();
    public void zhuan() {
        try {
            txManager.begin();
            accountService.zhuan();
            txManager.commit();
        } catch (Exception e) {
            e.printStackTrace();
            txManager.rollback();
        } finally {
            txManager.close();
        }
    }
    @Test
    public void test02(){
        //IAccountService accountService = new AccountService();
        IAccountService accountService = new AccountServiceNew();
        accountService.zhuan();
    }

执行结果中事务管理正常
静态代理的好处是,不改原代码,缺点就是编码量还是比较大

JDK动态代理添加事务代码

  • (1)在不改变源代码的基础上对目标方法进行增强
  • (2)动态代理的本质是生成一个新的类,叫代理类
  • (3)代理类中与目标类实现相同的接口
  • (4)代理类在运行时产生,在运行结束后销毁
    在这里插入图片描述
  @Test
    public void test03(){//JDK
        final AccountService accountService = new AccountService();//目标对象
        final MyTxManager myTxManager = new MyTxManager();//通知对象
        //代理类与代理对象 
        ClassLoader loader=accountService.getClass().getClassLoader();//参1 相同的加载器
        Class<?>[] interfaces=accountService.getClass().getInterfaces();//参2 相同的接口
        InvocationHandler handler = new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //参3 逻辑
                System.out.println("新类的对象 代理对象 "+proxy.getClass());
                System.out.println("切点方法  "+method.getName());
                System.out.println("切点参数  "+ Arrays.toString(args));
                try {
                    myTxManager.begin();
                    Object result =  method.invoke(accountService,args);
                    myTxManager.commit();
                    return result;
                } catch (Exception e) {
                    e.printStackTrace();
                    myTxManager.rollback();
                } finally {
                    myTxManager.close();
                }
                return null;
            }
        };
        IAccountService accountService1= (IAccountService) Proxy.newProxyInstance(loader,interfaces,handler);
       // accountService1.zhuan();
        accountService1.zhuan2();
    }

动态代理虽然也编写了不少代码,但是以后业务类方法增加,动态代理不需要再编写更多的事务管理的代码
比如业务类增加转账方法2

SpringAOP添加事务代码

  • (1)AOP即面向切面编程
  • (2)面向切面编程 底层执行的是动态代理
  • (3)面向切面编程,分两步
  • (4)1,使用切点表达式找出连接点中的切点方法
  • (5)2,编写增强逻辑 比如事务 就编写try,catch,finally
    》pom.xml设置依赖
 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.8</version>
        </dependency>

》applicationContext.xml设置 切面

  <!--     开始切面编程,确定切点,然后对切点进行 逻辑配置-->
    <bean class="com.huawei.tx.AccountService" id="accountService">
        <property name="accountDao" ref="accountDao"/>
    </bean>
    <bean class="com.huawei.tx.AccountDao" id="accountDao"/>
    <bean class="com.huawei.tx.MyTxManager" id="txManager"/>
    <aop:config>
        <!--  <aop:pointcut id="p1" expression="execution(修改符 返回值  方法名(参数))"/>-->
        <aop:pointcut id="p1" expression="execution( *  com.huawei.tx.*Service.*(..))"/>
        <aop:aspect ref="txManager">
            <!--四大位置-->
            <aop:before method="begin" pointcut-ref="p1"/>
            <aop:after-returning method="commit" pointcut-ref="p1"/>
            <aop:after-throwing method="rollback" pointcut-ref="p1"/>
            <aop:after method="close" pointcut-ref="p1"/>
        </aop:aspect>
    </aop:config>

》执行测试方法

 @Test
    public void test04(){

        IAccountService accountService = (IAccountService) context.getBean("accountService");
        System.out.println(accountService);
        accountService.zhuan();
    }

Spring声明式事务代码

  • (1)Spring的声明式事务管理是通过SpringAOP实现的
    最符合 非侵入式 轻量级容器的理念

》applicationContext.xml中设置切面

<!--    spring的声明式事务-->

    <bean id="tm"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--   Spring的事务是基于AOP,但是为了简化则采用样板风格,此处仅仅配置哪些方法名称需要切入事务-->
    <tx:advice id="advice" transaction-manager="tm">
        <tx:attributes>
            <!--       有就用,没有就创建一个新事务-->
            <tx:method name="insert*" propagation="REQUIRED"/>
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <!--        get query-->
            <tx:method name="find*" propagation="NEVER"/>
            <tx:method name="get*" propagation="NEVER"/>
            <tx:method name="*" propagation="NEVER"/>
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut expression="execution(* com.huawei.service..*Service.*(..))"
                      id="pointcut"/>
        <!--pointcut:切面表达式:指定包、类名称+tx 则是完整切面路径 -->
        <aop:advisor advice-ref="advice" pointcut-ref="pointcut"/>
    </aop:config>

》运行测试方法

  @Test
    public void test01(){
        //业务层需要处理事务,需要使用AOP
        //事务:一组操作要么全部成功,如果有一条失败就得回滚
        //转钱  -500 + 500
        IProductService iProductService = (IProductService) context.getBean("productService");
        iProductService.deleteProducts("1","2","3");
    }

SpringMVC介绍

  • (1)什么是 springmvc?
    Spring mvc属于表现层的框架,它是Spring框架的一部分

  • (2)SpringMVC的作用是?
    》接收请求,获取参数
    》处理参数
    》将结果响应给浏览器 如 重定向或者请求转发或者返回json
    在这里插入图片描述

SpringMVC的流程

  • (1)什么是 springmvc的工作流程?
  • (2)前端控制器将请求转给Controller
  • (3)Controller 处理三件事, 获取参数,处理参数,将结果返回给浏览器
    在这里插入图片描述

SpringMVC环境搭建

  • (1)设置pom.xml依赖
  • (2)设置tomcat
  • (3)设置web.xml
  • (4)设置web.xml 中加载springmvc.xml
  • (5)设置web.xml 中加载applicaitonContext.xml

<!--         springmvc 1 需要添加spring webmvc模块-->

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.1</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

打包方式改为war

   <!-- spring mvc2 修改打包方式-->
    <packaging>war</packaging>

新建 webapp目标

在这里插入图片描述
新建 web.xml

在这里插入图片描述
配置web.xml加载 springmvc.xml与applicationContext.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">

    <!--设置配置文件的路径  service dao-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>


    <!--解决中文乱码的过滤器-->
    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--配置Spring的监听器,默认只加载WEB-INF目录下的applicationContext.xml配置文件-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!--web.xml   配置前端控制器  DispatcherServlet , 还要加载springmvc.xml-->

    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <!--加载springmvc.xml
          init-param  是DispatcherServlet的初始化参数,指定springmvc的路径及文件名称
          当该Servlet 运行,springmvc的配置文件也会被加载进来
        -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>

        <!--设置servlet的启动加载时机
        load-on-startup  是servlet的加载时机, 1-5值,取值越小,加载时机越早
        -->
        <load-on-startup>2</load-on-startup>

    </servlet>

    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <!--
           配置方式3种:
           1.绝对路径   /UserServlet
           2.多级目录   /aaa/bbb/UserServlet
           3.通配符匹配    *.action   *.do   (只要请求的后置是.action 或.do都会执行该servlet)
        -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

配置springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
       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/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <!--springmvc是web层  UserController  @Controller -->
    <!-- 打开组件扫描-->
    <context:component-scan base-package="com.huawei">
        <!-- 只处理带@Controller的请求-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--配置的视图解析器对象 /WEB-INF/pages/success.jsp -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <!--过滤静态资源   .js .css png-->
    <mvc:resources location="/css/" mapping="/css/**" />
    <mvc:resources location="/images/" mapping="/images/**" />
    <mvc:resources location="/js/" mapping="/js/**" />
    <!--开启SpringMVC注解的支持 @RequestMapping @RequestBody @ResponseBody-->
    <mvc:annotation-driven/>
</beans>


修改applicationContext.xml中的组件扫描,不扫@Controller注解标记的类

   <!-- 扫描指定的目标,只要有@Service,@Repository  @Component-->
    <context:component-scan base-package="com.huawei">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

SpringMVC编写Controller

  • (1)编写Controller类
  • (2)配置@Controller注解
  • (3)@RequestMapping设置模块
  • (4)@RequestMapping设置方法路径与请求方式
//http://localhost:8080/
//当前类要由springMVc创建
@Controller
@RequestMapping(path = "/product")
public class ProductController {
    public ProductController() {
        System.out.println("ProductController构造方法执行");
    }
    //方法 = 方法名 + 参数 +返回值

    @Autowired
    IProductService productService ;

    @RequestMapping(path = "/list",method = RequestMethod.GET)
    public String list(){
      
        return "list-product";//去/WEB-INF/pages/找名为list-product.jsp的页面
    }

Controller方法中调用Service

  • (1)Service方法是经过单元测试的所以没有问题
  • (2)Controller只做三件事
  • (3)1,接收参数
  • (4)2,处理参数
  • (5)3,响应给浏览器
//http://localhost:8080/
//当前类要由springMVc创建
@Controller
@RequestMapping(path = "/product")
public class ProductController {
    public ProductController() {
        System.out.println("ProductController构造方法执行");
    }
    //方法 = 方法名 + 参数 +返回值

    @Autowired
    IProductService productService ;

    @RequestMapping(path = "/list",method = RequestMethod.GET)
    public String list(Model model){
        System.out.println("list被调用了");
        List<Product> list = productService.findAll();
        //请求转发 request  也可以使用Model
        model.addAttribute("list",list);
        return "list-product";//去/WEB-INF/pages/找名为list-product.jsp的页面
    }

jsp页面显示编写

在这里插入图片描述

  • (1)准备好jsp页面
  • (2)页面使用el表达式与c标签进行数据显示
    list-product.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
    <% pageContext.setAttribute("path",request.getContextPath()); %>
</head>
<body>
我是产品列表页面
<a href="${path}/product/toAdd">新建</a>
 <table width="100%" border="1">
     <tr>
         <td>id</td>
         <td>商品名</td>
         <td>商品价格</td>
         <td>操作</td>
     </tr>
     <c:forEach items="${list}" var="p">
         <tr>
             <td>${p.id}</td>
             <td>${p.name}</td>
             <td>${p.price}</td>
             <td><a href="${path}/product/delete?id=${p.id}">删除</a>|<a href="${path}/product/toUpdate?id=${p.id}">编辑</a></td>
         </tr>
     </c:forEach>

 </table>
</body>
</html>

在这里插入图片描述

删除方法编写

  • (1)接收参数,保需定义参数名与页面参数同名即可
  • (2)删除成功之后跳到列表页面
   @RequestMapping(path = "/delete",method = RequestMethod.GET)
    public String delete(String id){
        System.out.println("list被调用了");
        productService.deleteProducts(id);
        return "redirect:/product/list";
    }

添加方法编写

  • (1)先打开添加页面
  • (2)然后再将添加页面的表单数据使用实体对象接收
  • (3)调用service添加实体对象
  • (4)跳转到列表页面
    add-product.jsp

<form action="${path}/product/add" method="post">
    <table width="100%" border="1">

        <tr>

            <td>商品名 <input name="name" type="text"></td>

        </tr>
        <tr>
            <td>商品价格 <input name="price" type="text"></td>
        </tr>
        <tr>
            <td><input value="保存" type="submit"></td>
        </tr>

    </table>
</form>
    @RequestMapping(path = "/toAdd",method = RequestMethod.GET)
    public String toAdd(){

        return "add-product";
    }
    @RequestMapping(path = "/add",method = RequestMethod.POST)
    public String add(Product product){//使用表单对应的实体类可以接收
        productService.saveProduct(product);
        return "redirect:/product/list";
    }

回显方法编写

  • (1)先打开编辑页面,需要作一个回显操作
  • (2)先查询要编辑的数据
  • (3)再将数据显示在页面的输入框
  • (4)查询与显示合在一起叫做回显
<form action="${path}/product/update" method="post">
    <table width="100%" border="1">

        <tr>
             <input name="id" type="hidden" value="${p.id}">
            <td>商品名 <input name="name" type="text" value="${p.name}"></td>

        </tr>
        <tr>
            <td>商品价格 <input name="price" type="text" value="${p.price}"></td>
        </tr>
        <tr>
            <td><input value="保存" type="submit"></td>
        </tr>

    </table>
</form>
   @RequestMapping(path = "/toUpdate",method = RequestMethod.GET)
    public String toUpdate(String id,Model model){
        Product p = productService.findById(id);
        model.addAttribute("p",p);
        return "update-product";
    }


编辑方法编写

  • (1)使用Product product 变量接收页面提交的表单数据
  • (2)调用service将表单数据保存到数据库中
  • (3)保存成功之后跳到列表页面
    @RequestMapping(path = "/update",method = RequestMethod.POST)
    public String update(Product product){//使用表单对应的实体类可以接收
        productService.updateProduct(product);
        return "redirect:/product/list";
    }
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页