SSM学习笔记

本文为个人的学习笔记,仅作为学习记录笔记

Spring(IDEA)

一、概念

spring是分层的java SE/EE应用full-stack轻量级开源框架,以IoC(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)为内核。

二、优势

  1. 提供IoC容器,解耦;
  2. AOP编程的支持
  3. 声明式事务的支持
  4. 方便测试
  5. 方便集成各种框架
  6. 降低javaEE API的使用难度(封装)
  7. java源码可供学习

三、开发步骤

  1. 导入Spring开发的基本坐标

  2. 编写Dao接口和实现类

  3. 创建Spring核心配置文件

  4. 在Spring配置文件中配置UserDaoImpl

  5. 使用Spring的API获得Bean实例(getBean参数为配置的id)

    各步骤示例如下:

    • 在这里插入图片描述

    • 在这里插入图片描述

    3/4在这里插入图片描述
    在recourses中创建Spring配置文件,文件名原则上随意取
    5.在这里插入图片描述

四、Spring配置文件

4.1、Bean标签基本配置

用于配置对象交由Spring来创建。默认情况下他调用的是类中的无参构造,没有无参构造不会创建。

基本属性:id:Bean实例在Spring容器中的唯一标识;class:Bean的全限定名称

4.2、Bean标签范围配置

scope:指对象的作用范围,取值有:

  • singleton:默认值,单例的(在Spring中只会创建一个对象。多次new都只是同一个对象。spring核心文件加载时创建Bean对象
  • prototype:多例的(在Spring中可创建/new多个对象。在使用时"getBean()"创建Bean对象
  • request:Web中,Spring创建一个Bean对象,将对象存入到request域中
  • session:Web中,Spring创建一个Bean对象,将对象存入session域中
  • global session:在Web中,应用在portlet环境,如没有该环境,就等同于session
4.3、Bean的生命周期
  • init-method:初始化方法

  • destroy-method:销毁方法

    在这里插入图片描述

4.4、Bean实例化的三种方式
  1. 无参构造方法
  2. 工厂静态方法(factory-method)
  3. 工厂实例方法(factory-bean、factory-method)
4.5、Bean依赖注入
  • 通过set方法
    • 在这里插入图片描述

    • 在这里插入图片描述
      name:set的属性(userDao);ref:容器中的目标对象id(userDao)

  • 通过构造方法
    • 在这里插入图片描述

    • 在这里插入图片描述

依赖注入数据类型:

  • 普通数据类型

    • 在这里插入图片描述

    • 在这里插入图片描述

  • 引用数据类型(如上userService引用userDao)

  • 集合数据类型

    • 在这里插入图片描述

    • 在这里插入图片描述

4.6、import导入其他分标签
<import resource="applicationContext.xml"></import>

五、相关API

5.1、ApplicationContext

在这里插入图片描述

5.2、getBean()
  1. getBean(“id”):当存在多个相同的类时,只能使用id方式获取
  2. getBean(class):当某个类只存在一个时,可使用类来获取,不需要强转

六、连接池

6.1、c3p0
  1. 手动直接连接方式(导包)

    在这里插入图片描述

    导入的mysql的包版本在8.0以上要使用"com.mysql.cj.jdbc.Driver"驱动,并修改url中的时区问题

  2. 加载配置文件方式(.properties文件)

    在这里插入图片描述

    在这里插入图片描述

  3. Spring配置数据源

    在这里插入图片描述

    在这里插入图片描述

  4. Spring加载外部配置文件来配置数据源

    在这里插入图片描述

    需要注意,该配置方式需要在context命名空间中配置;同时使用SPEL表达式来设置内容

6.2、druid
  1. 手动直接使用方式

    在这里插入图片描述

    需要注意时区问题

  2. Spring配置数据源

    在这里插入图片描述

    在这里插入图片描述

七、注解开发

7.1、原始注解
  1. @Component :标准一个普通的spring Bean类

  2. @Repository:标注一个DAO组件类

    @Repository("userDao")
    public class userDaoImpl implements userDao {
    }
    
  3. @Service:标注一个业务逻辑组件类

    @Service("userService")
    public class userServiceImpl implements userService {
    }
    
  4. @Controller:标注一个控制器组件类


  5. @Autowired:属于Spring 的org.springframework.beans.factory.annotation包下,可用于为类的属性、构造器、方法进行注值

  6. @Qualifier(""):按照id名称从容器中匹配,需要结合Autowired

    @Autowired
    @Qualifier("userDao")
    private userDao userdao;
    //使用注解方式可以不用写set
    
  7. @Resource():不属于spring的注解,使用该annotation为目标bean指定协作者Bean;相当于@Autowired+@Qualifier("")

    @Resource(name = "userDao")
    private userDao userdao;
    

  8. @Value():注入普通属性

     @Value("${jdbc.driver}")
     private String Driver;
    
  9. @Scope():标注Bean的作用范围

  10. @PostConstruct:标注在方法上,表示该方法是Bean的初始化方法

  11. @PreDestroy:标注在方法上,表示该方法是Bean的销毁方法

注意,在使用竹节时,需要在配置文件中扫描注解,基包为扫描对象及其子包

<context:component-scan base-package="com.zjj.maven"/>
7.2、新注解
  1. @Configuration:声明当前类是一个配置类(相当于一个Spring配置的xml文件)

  2. @ComponentScan:自动扫描指定包下所有使用@Service,@Component,@Controller,@Repository的类并注册

    <context:component-scan base-package="com.zjj.maven"/>   //相当于
    
  3. @Bean:注解在方法上,声明当前方法的返回值为一个Bean。注册一个Bean,值为方法的返回值

  4. @PropertySource:指定文件地址。提供了一种方便的、声明性的机制,用于向Spring的环境添加PropertySource。与@configuration类一起使用。

    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>  //相当于
    
  5. @Import(xxx.class):导入文件

具体实例:

//核心配置文件(总配置类)
@Configuration  //标记为配置类
@ComponentScan("com.zjj.maven")    //扫描范围
@Import(dataSourceConfig.class)    //导入文件
public class springConfiguration {
}
//分配置类,通过import导入注配置类
@PropertySource("classpath:jdbc.properties")   //导入properties文件
public class dataSourceConfig {
    @Value("${jdbc.driver}")     //注入普通数据类型
    private String Driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    @Bean("dataSource")     //注册一个Bean,为方法的返回值
    public DataSource getDataSource()throws  Exception{
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass(Driver);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(username);
        dataSource.setPassword(password);
        return dataSource;
    }
}
//加载配置类
ApplicationContext app = new AnnotationConfigApplicationContext(springConfiguration.class);
userService userService = (userService)app.getBean("userService");
DataSource dataSource = (DataSource) app.getBean("dataSource");
Connection conn = dataSource.getConnection();
7.3、springJunit集成测试
  1. 导入spring集成junit坐标
  2. @Runwith代替原来的运行期
  3. @ContextConfiguration指定配置文件或类
  4. @Autowired注入测试对象
  5. 创建测试放进行测试

如下:

<!--导入集成junit坐标-->
<dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-test</artifactId>
       <version>5.0.5.RELEASE</version>
 </dependency>

@RunWith(SpringJUnit4ClassRunner.class)   //代替原来的 运行期
//@ContextConfiguration("classpath:applicationContext.xml")     //指定配置文件
@ContextConfiguration(classes = {springConfiguration.class})    //指定配置类
public class springJunitTest {
    @Autowired    //注入数据
    private userService userService;
    @Autowired
    private DataSource dataSource;

    @Test
    public void test2() throws Exception{
        Connection conn = dataSource.getConnection();
        System.out.println(conn);
        conn.close();
    }

    @Test
    public void test1(){
        userService.save();
    }
}

八、AOP

AOP(Aspect Oriented Programming:面向切面编程)

8.1、代理模式
  1. 静态代理

    • 继承:通过继承父类,重写方法实现

      //目标对象
      public class Target {
          public void save(){
              System.out.println("saving...");
          }
      }
      
      //代理对象
      public class Proxy extends Target {
          @Override
          public void save() {
              System.out.println("before");   //增强
              super.save();
          }
      }
      
      //使用代理对象
      public class test {
          public static void main(String[] args) {
              Proxy proxy = new Proxy();
              proxy.save();
          }
      }
      
      //输出:
      //before
      //saving...
      
    • 聚合:通过实现接口来实现代理

      //接口
      public interface Inte {
          public void save();
      }
      
      //目标对象
      public class Target implements Inte{
      
          @Override
          public void save() {
              System.out.println("saving");
          }
      }
      
      //代理对象
      public class Proxy implements Inte {
          private Target target;
          public Proxy(Target tar){
              this.target = tar;
          }
          @Override
          public void save() {
              System.out.println("before...");//增强
              target.save();
              System.out.println("after...");//增强
          }
      }
      
      //实现
      public class test {
          public static void main(String[] args) {
              Target tar = new Target();
              Proxy proxy = new Proxy(tar);
              proxy.save();
          }
      }
      
      //输出:
      //before...
      //saving...
      //after...
      
  2. 动态代理(JDK)兄弟关系

    //接口
    public interface TargetInterface {
        public void save();
    }
    
    //目标对象
    public class Target implements TargetInterface {
        @Override
        public void save() {
            System.out.println("save...");
        }
    }
    
    //增强方法
    public class Advice {
        public void before(){
            System.out.println("before...");
        }
        public void after(){
            System.out.println("after...");
        }
    }
    
    //代理实现
    public class PorxyTest {
        public static void main(String[] args) {
            //目标对象
            Target target = new Target();
            //增强对象
            Advice advice = new Advice();
            //返回值,动态生成的代理对象;newProxyInstance包含三个参数
            TargetInterface  invoke = (TargetInterface) Proxy.newProxyInstance(
                    target.getClass().getClassLoader(),   //目标对象类加载器
                    target.getClass().getInterfaces(),    //目标对象相的接口字节码对象数组,因此可代理多个接口的对象
                    new InvocationHandler() {
                        //调用代理对象的任何方法,实质上调用的时invoke的方法
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            advice.before();    //前置增强
                            Object invoke = method.invoke(target, args);   //执行目标方法
                            advice.after();    //后置增强
                            return invoke;
                        }
                    }
            );
            //调用代理对象方法
            invoke.save();
        }
    }
    //输出:
    //before...
    //save...
    //after...
    
  3. 动态代理(cglib)父子关系

    //目标对象
    public class Target implements TargetInterface {
        @Override
        public void save() {
            System.out.println("save...");
        }
    }
    
    
    //增强方法
    public class Advice {
        public void before(){
            System.out.println("before...");
        }
        public void after(){
            System.out.println("after...");
        }
    }
    
    //创建代理并实现
    public class PorxyTest {
        public static void main(String[] args) {
            //目标对象
            Target target = new Target();
            //增强对象
            Advice advice = new Advice();
            //动态代理对象。基于cglib
            //1.创建增强器
            Enhancer enhancer = new Enhancer();
            //2.设置父类(目标)
            enhancer.setSuperclass(Target.class);
            //3.设置回调
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    advice.before();  //前置方法
                    Object invoke = method.invoke(target, args);    //目标对象方法
                    advice.after();   //后置方法
                    return invoke;
                }
            });
            //创建代理对象
            Target invoke = (Target) enhancer.create();
    
            invoke.save();
        }
    }
    //输出:
    //before...
    //save...
    //after...
    
8.2、相关概念
  1. Target(目标对象):代理的目标对象
  2. Porxy(代理):一个类被AOP织入增强后,就产生一个代理类
  3. Joinpoint(连接点):能够被拦截到的方法,泛指方法
  4. Pointcut(切入点):对哪些连接点进行拦截的定义
  5. Advice(通知/增强):拦截到连接点后需要做的事情
  6. Aspect(切面):时切入点和通知的结合
  7. Weaving(织入):将增强应用到目标对象来创建代理的过程
8.3、xml方式配置
  1. 配置步骤:

    • 导入AOP相关坐标

      <dependencies>
              <dependency>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-context</artifactId>
                  <version>5.0.5.RELEASE</version>
              </dependency>
              <dependency>
                  <groupId>org.aspectj</groupId>
                  <artifactId>aspectjweaver</artifactId>
                  <version>1.9.6</version>
              </dependency>
              <dependency>
                  <groupId>org.springframework</groupId>
                  <artifactId>spring-test</artifactId>
                  <version>5.0.5.RELEASE</version>
              </dependency>
              <dependency>
                  <groupId>junit</groupId>
                  <artifactId>junit</artifactId>
                  <version>4.12</version>
              </dependency>
          </dependencies>
      
    • 创建目标接口和目标类(内部有切点)

      //目标类
      public class Target implements TargetInterface {
          @Override
          public void save() {
              System.out.println("save...");
          }
      }
      
    • 创建切面类(内部有增强方法)

      public class MyAspect {
          public void before(){
              System.out.println("before...");
          }
          public void after(){
              System.out.println("after...");
          }
      }
      
    • 将目标类和切面类的对象创建权交给spring

    • 在applicationContext.xml中配置织入关系

      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:aop="http://www.springframework.org/schema/aop" 
             xsi:schemaLocation="
             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
             http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <bean id="target" class="com.zjj.maven.aop.Target"></bean>  
          <bean id="MyAspect" class="com.zjj.maven.aop.MyAspect"></bean>  
      
          <aop:config>    <!--织入配置-->
              <aop:aspect ref="MyAspect">   <!--确定切面-->
                  <aop:before method="before" pointcut="execution(public void com.zjj.maven.aop.Target.save())"></aop:before>   <!--确定切点和增强:前置-->
                  <aop:after method="after" pointcut="execution(public void com.zjj.maven.aop.Target.save())"></aop:after>  <!--确定切点和增强:后置-->
              </aop:aspect>
          </aop:config>
      </beans>
      
    • 测试

      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration("classpath:applicationContext.xml")
      public class aopTest {
          @Autowired
          private TargetInterface tar;
          @Test
          public void test(){
              tar.save();
          }
      }
      //输出:
      //before...
      //save...
      //after...
      
  2. 切点表达式语法:

    execution([修饰符] 返回值类型 包名.类名.方法名(参数))

    • 修饰符可省略
    • 返回值类型、包名、类名、方法名可以使用*代表任意
    • 包名与类名之间一个.代表当前包下的类,两个…表示当前包及其子包的类
    • 参数列表可以使用两个点…表示任意参数
  3. 通知的类型:

    • 前置通知

      <aop:before>
      
    • 后置通知

      <aop:after-returning>
      
    • 环绕通知

      <aop:around>
      
    • 异常抛出通知

      <aop:throwing>
      
    • 最终通知

      <aop:after>
      
8.4、注解方式配置
  1. 配置步骤:

    • 创建目标接口类和目标类

      @Component("Target")
      public class Target implements TargetInterface {
          @Override
          public void save() {
              System.out.println("save...");
          }
      }
      
    • 创建切面类

    • 将目标类和切面类的对象创建权交给spring

    • 在切面类中使用注解配置织入关系

      @Component("MyAspect")
      @Aspect                          //设置切面
      public class MyAspect {
          @Before("execution(public void com.zjj.maven.aop_anno.*.*(..))")   //织入
          public void before(){
              System.out.println("before...");
          }
          public void after(){
              System.out.println("after...");
          }
      }
      
    • 在配置文件中开启扫描和AOP的自动代理

         <context:component-scan base-package="com.zjj.maven.aop_anno"></context:component-scan>   <!--组件扫描-->
         <aop:aspectj-autoproxy></aop:aspectj-autoproxy>   <!--aop自动代理-->
      
    • 测试

      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration("classpath:applicationContext_anno.xml")
      public class aop_annoTest {
          @Autowired
          private TargetInterface target;
          @Test
          public void test(){
              target.save();
          }
      }
      //输出:
      //before...
      //saving...
      
  2. 注解类型:

    • 通知注解类型

      • @Before — 前置通知
      • @AfterReturning — 后置通知
      • @Around — 环绕通知(目标对象默认不执行,需要手动执行)
      • @After — 最终通知
      • @AfterThrowing — 异常抛出通知
    • 切点表达式抽取

          @After("pointcut()")   //直接使用抽取的切点表达式的方法
          public void after(){
              System.out.println("after...");
          }
      
      //在切面类中定义一个方法,为该方法添加注解Pointcut,内容为切点表达式
          @Pointcut("execution(public void com.zjj.maven.aop_anno.*.*(..))")
          public void pointcut(){}
      

九、Spring jdbcTemplate

9.1、开发步骤:
  1. 导入相关坐标

    <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>5.0.5.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-tx</artifactId>
                <version>5.0.5.RELEASE</version>
            </dependency>
    
  2. 创建数据库表和实体

  3. 创建jdbcTemplate对象

     <!--配置文件配置,并创建对象-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/student?serverTimezone=UTC&amp;useSSL=false"></property>
            <property name="user" value="root"></property>
            <property name="password" value="root"></property>
        </bean>
    
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    
    //加载配置文件
    ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
    JdbcTemplate jdbc = app.getBean(JdbcTemplate.class);
            
    
  4. 执行数据库操作

    		int row = jdbcTemplate.update("insert into t_user (id,username,password,hobby,email) values (?,?,?,?,?)", "1111111", "zhangsan", "123456", "hobby", "4565464");
            System.out.println(row);
    
9.2、CURD:
  1. 增删改

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class TestCURD {
        @Autowired
        private JdbcTemplate jdbc;
    
        @Test
        public void testAdd() {
            jdbc.update("insert into user (id,name) values (?,?)", "1", "zhangsan");
        }
    
        @Test
        public void TestUpdate() {
            jdbc.update("update user set name=? where id=?", "lisi", "1");
        }
    
        @Test
        public void TestDelete(){
            jdbc.update("delete from user where name=?","lisi");
        }
    }
    
  2.     @Test
        /*查询全部数据,参数为:sql+bean属性行映射(封装到实体类中),返回值为集合*/
        public void TestQueryAll(){
            List<UserEntity> list = jdbc.query("select * from user", new BeanPropertyRowMapper<UserEntity>(UserEntity.class));
            System.out.println(list);
        }
    
        @Test
        /*查询单个数据,参数为:sql+bean属性行映射(封装到实体类中)+参数,返回值为对象*/
        public void TestQueryOne(){
            UserEntity sd = jdbc.queryForObject("select * from user where name=?", new BeanPropertyRowMapper<UserEntity>(UserEntity.class), "sd");
            System.out.println(sd);
        }
    
        @Test
        /*查询数量,返回值为简单数据类型,参数为类型.class*/
        public void TestQueryCount(){
            Integer count = jdbc.queryForObject("select count(*) from user", Integer.class);
            System.out.println(count);
        }
    

十、声明式事务控制

10.1、xml方式

实例:

  • DAO

    public class accountDaoImpl implements accountDao {
        private JdbcTemplate jdbc;
        public accountDaoImpl (JdbcTemplate jdbcTemplate){this.jdbc = jdbcTemplate;}
        @Override
        public void updateIn(String InName,double Inmoney) {
            int update = jdbc.update("update myaccount set money=money+? where username=?", Inmoney, InName);
        }
        @Override
        public void updateOut(String OutName,double Outmoney) {
            int update = jdbc.update("update myaccount set money=money-? where username=?", Outmoney, OutName);
        }
    }
    
  • SERVICE

    public class accountServiceImpl implements accountService {
        private accountDao accountDao;
        public accountServiceImpl(accountDao accountDao){this.accountDao = accountDao;}
        @Override
        public void transimt(String Outname, String InName, double money) {
            accountDao.updateIn(InName,money);
            int a = 5/0;
            accountDao.updateOut(Outname,money);
        }
    }
    
  • CONTROLLER

     public static void main(String[] args) {
            ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
            accountService bean = (accountService) app.getBean("accountService");
            bean.transimt("zhangsan","lisi",5000);
        }
    
  • XML

     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/account?serverTimezone=UTC&amp;useSSL=false"></property>
            <property name="user" value="root"></property>
            <property name="password" value="root"></property>
        </bean>
    
        <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    
        <bean id="accountDao" class="com.zjj.maven.Dao.Impl.accountDaoImpl">
            <constructor-arg ref="template"></constructor-arg>
        </bean>
    
        <!--目标对象-->
        <bean id="accountService" class="com.zjj.maven.Service.Impl.accountServiceImpl">
            <constructor-arg ref="accountDao"></constructor-arg>
        </bean>
    
        <!--配置平台事务管理器-->
        <bean id="transactionManagement" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    
        <!--通知,事务增强-->
        <tx:advice id="tx-ddvice" transaction-manager="transactionManagement">
            <tx:attributes>
                <tx:method name="*"/>
                <tx:method name="save" isolation="DEFAULT" timeout="-1" read-only="false" propagation="MANDATORY"/>
            </tx:attributes>
        </tx:advice>
    
        <!--method: 切点事务参数配置
            name:切点方法名
            isolation:事务隔离级别
            propagation:事务传播行为
            timeout:超时事件
            read:事都只读
        -->
    
        <!--织入-->
        <aop:config>
            <aop:advisor advice-ref="tx-ddvice" pointcut="execution(* com.zjj.maven.Service.Impl.accountServiceImpl.transimt(..))"></aop:advisor>
        </aop:config>
    
10.2、注解方式
  1. 为Dao、Service类添加注解使其注册到spring容器中(@Repository(“accountDao”)、@Service(“accountService”))

  2. 在xml中配置扫描组件

     <context:component-scan base-package="maven"/>  <!--扫描注解-->
    
  3. 为切点增加通知和织入

     @Transactional(isolation = Isolation.DEFAULT)    //可添加事务参数配置,可配置在类上(表示该泪下全部);可配置在方法上(就近原则)
        public void transimt(String Outname, String InName, double money) {
            accountDao.updateIn(InName,money);
            int a = 5/0;
            accountDao.updateOut(Outname,money);
        }
    
  4. 咋xml中配置注解事务驱动

    <tx:annotation-driven transaction-manager="transactionManagement"/>    <!--注解事务驱动-->
    

十一、Spring集成Web开发环境

11.1、开发环境
  1. POM.xml配置

            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet.jsp</groupId>
                <artifactId>javax.servlet.jsp-api</artifactId>
                <version>2.3.3</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>5.0.5.RELEASE</version>
            </dependency>
    

2.Web层application文件加载(将加载放在ContextLoaderListener监听器中,输入spring封装工具)

<!--web.xml配置-->  
<!--全局初始化参数 -->
<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
<!--配置监听器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
@WebServlet("/test")
public class userServlet extends HttpServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        ServletContext servletContext = req.getServletContext();  //获得ServletContext域对象
        //使用WebApplicationContextUtils工具类自动在监听器中加载xml配置文件,并返回一个ApplicationContext对象
        ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext);  
        userServiceImpl bean = app.getBean(userServiceImpl.class);
        bean.save();
    }
}

SpringMVC

一、开发步骤

  1. 导入SpringMVC相关坐标 (pom.xml)

     		<dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>5.0.5.RELEASE</version>
            </dependency>
    
  2. 配置SpringMVC核心控制器DispathcerServlet (web.xml)

    <!--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>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>DispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
  3. 创建Controller类和视图界面

  4. 使用注解配置Controller类中业务方法的映射地址

    @Controller("userController")
    public class userController {
        @RequestMapping("/saving")
        public String saving(){
            System.out.println("userController runner...");
            return "success.jsp";    //跳转界面
        }
    }
    
  5. 配置SpringMVC核心文件spring-mvc.xml

     <contrext:component-scan base-package="com.zjj.web01.Controller"></contrext:component-scan>
    
  6. 测试

二、注解解析

2.1、@RequestMapping
  • 用于建立请求URL和建立请求方法之间的对应关系

  • 可作用于类上(URL的一级目录,相当于根目录)和方法上(URL的二级目录)

  • 参数:value method params

    @RequestMapping(value = "/saving",method = RequestMethod.POST,params = {"aaa"})
    
2.2、@ResponseBody
  • 用于回写数据
  • 告知SpringMVC框架,不进行试图跳转,直接返回数据
2.3、@RequestBody
  • 该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter进行解析,然后把相应的数据绑定到要返回的对象上

  • 再把HttpMessageConverter返回的对象数据绑定到 controller中方法的参数上。

  • 处理格式:application/json, application/xml等,置于方法参数前

    public void test5(@RequestBody List<userEntity> list){
            System.out.println(list);
        }
    
2.4、@RequestParam
  • 用于绑定请求参数与方法的参数;当请求参数名与方法名不一样时且请求参数与方法参数不匹配时,将请求参数映射到参数上

  • 注解参数:

    • value:请求参数的名称
    • required:请求参数是否允许为空(否:true;是:false)
    • defaultValue:默认值
//请求:http://localhost:8080/getValue/query6?name=xxx   
@RequestMapping("query6")
    @ResponseBody
    public void test6(@RequestParam(value = "name",required = false, defaultValue = "aaa") String username) {
        System.out.println(username);
    }
//输出
//xxx
2.5、@PathVariable
  • 用于Restful风格的参数设置

  • 请求参数通过url路径来传输,而是不用连接符携带传输

       //请求:http://localhost:8080/getValue/query7/zhangsan   
        @RequestMapping("query7/{username}")    //需要在路径后添加占位符,即实际参数
        @ResponseBody
        public void test7(@PathVariable(value = "username") String username) {  //使用注解解析,value应与占位符内相同
            System.out.println(username);
        }
    
    //输出
    //zhangsan
    
2.6、@RequestHeader
  • 获得请求头信息
  • 参数:
    • value:请求头中具体信息
    • required:是否必须包含该信息(true:是,false:否)
   //获得请求头中的content_type信息
	@RequestMapping("query9")
    @ResponseBody
    public void test9(@RequestHeader(value = "content-type",required = false) String content_type) {
        System.out.println(content_type);
    }
2.7、@CookieValue
  • 获得请求的Cookie值
  • 参数
    • value:请求头中具体信息
    • required:是否必须包含该信息(true:是,false:否)
   //获得JSESSIONID 	
	@RequestMapping("query10")
    @ResponseBody
    public void test10(@CookieValue(value = "JSESSIONID") String jsessionId) {
        System.out.println(jsessionId);
    }

//直接得到JSESSIONID字符串

三、Spring_mvc.xml配置相关

3.1、资源内部视图解析器配置
    <!--内部资源视图解析器配置-->
    <bean id="InternalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/jsp/"></property>   <!--配置视图资源前置信息-->
        <property name="suffix" value=".jsp"></property>    <!--配置视图资源后缀信息-->
    </bean>
//在@ResquestMapping注解映射的方法中,可以胜率一些重复的信息
return "success";    //如果不配置,则应写的资源路径为:"/jsp/success.jsp"
3.2、处理器映射器配置
    <!--配置处理器映射器-->
    <bean id="RequestMappingHandlerAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
            </list>
        </property>
    </bean>

(通过该项配置,可以使在回写数据时,SpringMVC框架自动将类转换成json格式回写)

该配置可以简化:

 <mvc:annotation-driven></mvc:annotation-driven> <!--由此代替上面的配置信息-->
3.3、静态资源开放

SpringMVC 默认不开放静态资源

  • 方法一

    使用mvc:resources标签,mapping表示webapp下的路径,”/“可视为webapp文件夹;location表示哪个目录下的资源开放,一般为"/xx/"格式

    <mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
    
  • 方法二

    开放所有静态文件资源(当SpringMVC找不到静态资源时,tomcat服务器会去寻找,即开放所有)

    <mvc:default-servlet-handler></mvc:default-servlet-handler>
    
3.4、文件上传解析器

配置文件上传解析器即可实现文件上传,此处使用CommonMutipartResolver来配置(也可使用StandardServletMutipartResolver配置,区别在于:后者需要依赖servlet3.0以上版本;前者基于apache不需要该版本依赖,只需要导入依赖包即可commons-fileupload,详见6.2)。

<!--配置文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="defaultEncoding" value="UTF-8"></property>
        <property name="maxUploadSize" value="500000"></property>
    </bean>

需要注意:在配置时,bean的id应为"multipartResolver",应为在源码中,spring默认会自动从上下文中寻找id为multipartResolver的bean作为MultipartResolver,如修改,会导致上传失败

3.5、拦截器配置
    <!--配置拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--对哪些资源进行拦截-->
            <mvc:mapping path="/**"/>
            <bean class="com.zjj.maven.interceptor.Myinterceptor1"></bean>     <!--拦截器类全限定名-->
        </mvc:interceptor>
    </mvc:interceptors>
3.6、异常处理配置
  1. 简单异常处理器配置

    <!--简单异常处理器-->
        <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
            <property name="defaultErrorView" value="error"></property>    <!--默认异常跳转视图-->
            <property name="exceptionMappings">
                <map>
                    <entry key="java.lang.ClassCastException" value="error1"></entry>    <!--如果出现此异常,进入类型转换异常视图-->
                    <entry key="java.lang.ArithmeticException" value="error2"></entry>   <!--如果出现此异常,进入除数为0常视图-->
                </map>
            </property>
        </bean>
    
  2. 自定义异常处理器

    <!--只需要将异常处理类加入到容器中即可-->
    <bean class="com.zjj.maven.Resolver.MyExceptionResolver"></bean>
    

四、SpringMVC的数据响应

4.1、页面跳转
  • 直接返回字符串

     @RequestMapping(value = "/saving",params = {"aaa"})
        public String saving(){
            System.out.println("userController runner...");
            return "forward:/jsp/success.jsp";    //转发
        } 
    
     @RequestMapping(value = "/saving",params = {"aaa"})
        public String saving(){
            System.out.println("userController runner...");
            return "redirect:/jsp/success.jsp";   //重定向
        }    
    
  • 通过ModelAndView对象返回

     @RequestMapping(value = "/saving2")
        public ModelAndView saving2(){      //返回ModelAndView
            ModelAndView modelAndView = new ModelAndView();
            //设置模型数据
            modelAndView.addObject("username","zjj");    //类似于request域的setAttrabute
            //设置试图名称
            modelAndView.setViewName("forward:/jsp/success.jsp");   //页面跳转,使用重定向将无法将数据发送至页面(request域同理)
            return modelAndView;
        }
    
    <p>username:${username}</p>    <!--重定向将无法接收到模型中的数据-->
    
  • mode 和 view分开

        @RequestMapping(value = "/saving3")
        public String saving3(Model model){  //注入model
            //设置模型数据
            model.addAttribute("username","zjj");
            return "/jsp/success.jsp";
        }
    
4.2、回写数据
  • 直接返回字符串

        @RequestMapping(value = "/saving4")
        @ResponseBody    //告知SpringMVC框架,不进行试图跳转,直接返回数据
        public String saving4(){
            //返回数据
            return "HELLO WORLD";   
        }
    

    实例应用:

        @RequestMapping(value = "/saving5")
        @ResponseBody    //告知SpringMVC框架,不进行试图跳转,直接返回数据
        public String saving5() throws JsonProcessingException {
            //实体对象
            userEntity userEntity = new userEntity();
            userEntity.setUserName("zjj");
            userEntity.setAge(21);
            //json转化
            ObjectMapper objectMapper = new ObjectMapper();
            String json = objectMapper.writeValueAsString(userEntity);
            //返回数据
            return json;
        }
    
  • 返回对象或集合

    //此方式需要配置  处理器映射器 ;详细配置信息可见3.2
        @RequestMapping(value = "/saving6")
        @ResponseBody    //告知SpringMVC框架,不进行试图跳转,直接返回数据
        public userEntity saving6(){
            //实体对象
            userEntity userEntity = new userEntity();
            userEntity.setUserName("zjj");
            userEntity.setAge(21);
            //返回数据
            return userEntity;
        }
    

五、SpringMVC获得请求数据

5.1、获得请求的参数
  1. 基本类型参数 (直接在Controller类中方法中传入相关数据名称参数即可)

    //请求:/query1?name=zjj&age=15&sex=nan
    
        @RequestMapping("query1")
        @ResponseBody
        public void test1(String name, int age, String sex){     //传入请求中的相关参数的名称
            System.out.println(name);
            System.out.println(age);
            System.out.println(sex);
        }
    
  2. POJO类型参数 (传入实体类,可自动封装到实体类中)

    //请求:/query2?name=zjj&age=15
    
        @RequestMapping("query2")
        @ResponseBody
        public void test2(userEntity userEntity){     //传入如请求中参数一致的实体类,MVC将自动将数据封装至实体类中
            System.out.println(userEntity);
        }
    
  3. 数组类型参数

    //请求:/query3?str=gggg&str=pppp&str=saaaaa
    
        @RequestMapping("query3")
        @ResponseBody
        public void test3(String []str){     //传入与参数名称相同的数组
            System.out.println(Arrays.asList(str));
        }
    
  4. 集合类型参数

    需要创建一个VO类封装有实体类的集合,将表单数据传入该集合实现封装

    //VO类
    public class VO {
        private List<userEntity> userList;       //泛型为实体类的集合
        public List<userEntity> getUserList() {
            return userList;
        }
        public void setUserList(List<userEntity> userList) {
            this.userList = userList;
        }
        @Override
        public String toString() {
            return "vo{" +
                    "userList=" + userList +
                    '}';
        }
    }
    
    //Controller
        @RequestMapping("query4")
        @ResponseBody
        public void test4(VO vo){    //传入VO类
            System.out.println(vo);
        }
    
    <!--表单-->
    <form action="/getValue/query4" method="post">
        用户1的id:<input name="userList[0].userName"><br>
        用户1的age:<input name="userList[0].age"><br>
        用户2的id:<input name="userList[1].userName"><br>
        用户2的age:<input name="userList[1].age"><br>
        <input type="submit" value="提交">
    </form>
    

    案例二:(使用注释加ajax类传输获得集合数据)

    @RequestMapping("query5")
    @ResponseBody
    public void test5(@RequestBody List<userEntity> list){    //@RequestBody使用该注释可直接获得集合,详见2.3
        System.out.println(list);
    }
<!--ajax请求-->
<body>
<script src="/js/jquery-3.5.1.js"></script>
<script>
    var userList = new Array();
    userList.push({"userName":"aaa","age":16});
    userList.push({"userName":"bbb","age":18});
    $.ajax({
        type:"POST",
        url:"${pageContext.request.contextPath}/getValue/query5",
        contentType:"application/json;charset=utf-8",
        data : JSON.stringify(userList)              /*转化为json格式数据*/
    });
</script>
</body>

需要注意:SpringMVC默认不开放静态资源(如js、css等静态文件夹中的资源),需要配置开放静态资源,详见3.3

5.2、请求乱码问题

通过web.xml配置全局过滤设置编码

    <!--配置全局过滤filter-->
    <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>
5.3、自定义类型转换器

步骤:

  1. 定义转换器类实现Converter接口

    public class DateConverter implements Converter<String,Date>{    //请求参数类型,转换类型
        @Override
        public Date convert(String s) {
            SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd");
            Date date = null;
            try {
                date = format.parse(s);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return date;   //返回日期
        }
    }
    
  2. 在配置文件中声明转换器

        <!--声明自定义转换器-->
        <bean  id="conversionServiceFactory" class="org.springframework.context.support.ConversionServiceFactoryBean">
            <property name="converters">
                <list>
                    <bean class="com.zjj.web01.converter.DateConverter"></bean>    <!--绑定自定义转换器的全限定名-->
                </list>
            </property>
        </bean>
    
  3. 在<annotation - driven> 中引用转换器

        <mvc:annotation-driven conversion-service="conversionServiceFactory"></mvc:annotation-driven>
    
  4. 测试

       //请求:http://localhost:8080/getValue/query8?date=2021-1-25
    	@RequestMapping("query8")
        @ResponseBody
        public void test8(Date date) {
            System.out.println(date);
        }
    //输出:
    //Mon Jan 25 00:00:00 CST 2021
    

六、文件上传

6.1、文件上传三要素
  1. 表单项type=“file”

  2. 表单的提交方式时post

  3. 表单的enctype属性时多部分表单形式,即enctype=“multipart/form-data”

    <form action="/file/load1" method="post" enctype="multipart/form-data">
        名称:<input  name="name"/><br>
        文件:<input  type="file" name="file"/><br>
        <input type="submit" value="上传"/>
    </form>
    
6.2、单文件上传步骤
  1. 导入fileipload和io坐标

    	    <dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>1.3.1</version>
            </dependency>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.5</version>
            </dependency>
    
  2. 配置文件上传解析器

    <!--配置文件上传解析器,详见3.4-->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <property name="defaultEncoding" value="UTF-8"></property>
            <property name="maxUploadSize" value="500000"></property>
        </bean>
    
  3. 编写文件上传代码

    @RequestMapping(value = "load1",method = RequestMethod.POST)
    @ResponseBody
    public void test1(String name, MultipartFile file){
        System.out.println(name);
        //获得文件名
        String originalFilename = file.getOriginalFilename();
        try {
            //将文件写入服务器磁盘,该方法为其自带方法
            file.transferTo(new File("C:\\Users\\18264\\Desktop\\学习文档\\"+ originalFilename));
        } catch (IOException e) {
            e.printStackTrace();
        }
    
    }
    
6.3、多文件上传
  1. 表单

    <form action="/file/load1" method="post" enctype="multipart/form-data">
        名称:<input  name="name"/><br>
        文件1:<input  type="file" name="file"/><br>   <!--文件name相同-->
        文件2:<input  type="file" name="file"/><br>
        <input type="submit" value="上传"/>
    </form>
    
  2. 文件上传代码

        @RequestMapping(value = "load1",method = RequestMethod.POST)
        @ResponseBody
        public void test1(String name, MultipartFile[] file){   //使用数组接收
            System.out.println(name);
            try {
                for(MultipartFile m : file){    //遍历存盘
                    String originalFilename = m.getOriginalFilename();
                    file.transferTo(new File("C:\\Users\\18264\\Desktop\\学习文档\\"+ originalFilename));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    

七、SpringMVC拦截器

  • SpringMVC拦截器相当于 servlet 中的 filter
  • SpringMVC拦截器也是AOP的一种具体体现
7.1、Filter与SpringMVC拦截器
FilterSpringMVC
拦截范围整个Web项目中可以使用只能在MVC框架中使用
拦截对象可以拦截所有资源(包括servlet和静态资源js、css等)只能拦截Controller中的方法,不能拦截静态资源
7.2、拦截器实现步骤
  1. 创建拦截器类实现HandlerInterceptor接口

    public class Myinterceptor1 implements HandlerInterceptor {
        //在目标方法执行之前执行
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle");
            return true;     //设置为true,放行
        }
        //在目标方法执行之之后,视图(view)返回之前
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle");
        }
        //在目标方法整个流程执行完毕之后执行
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion");
        }
    }
    
    
  2. 配置拦截器

        <!--配置拦截器-->
        <mvc:interceptors>
            <mvc:interceptor>
                <!--对哪些资源进行拦截-->
                <mvc:mapping path="/**"/>
                <bean class="com.zjj.maven.interceptor.Myinterceptor1"></bean>
            </mvc:interceptor>
        </mvc:interceptors>
    
  3. 测试拦截器的拦截效果

    //输出:
    //preHandle
    //目标资源执行
    //postHandle
    //afterCompletion
    

八、SpringMVC异常处理机制

8.1、简单异常处理器:SimpleMappingExceptionResolver
  • 异常处理器配置

        <!--异常处理器,,,详见3.6-->
        <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
            <property name="defaultErrorView" value="error"></property>    <!--默认异常跳转视图-->
            <property name="exceptionMappings">
                <map>
                    <entry key="java.lang.ClassCastException" value="error1"></entry>    <!--如果出现此异常,进入类型转换异常视图-->
                    <entry key="java.lang.ArithmeticException" value="error2"></entry>   <!--如果出现此异常,进入除数为0常视图-->
                </map>
            </property>
        </bean>
    
  • Controller

    @Controller("exception")
    public class ExceptionConTest {
        @Autowired
        private userService userService;
        //除数为0异常
        @RequestMapping("exception2")
        public String show2() throws Exception{
            userService.show2();
            return "index";
        }
        //类型转换异常
        @RequestMapping("exception1")
        public String show1() throws Exception{
            userService.show1();
            return "index";
        }
    }
    
  • Service

    public class userService {
         //类型转换异常
        public void show1(){
            System.out.println("类型转换异常");
            Object str = "xxx";
            Integer num = (Integer) str;
        }
         //除数为0异常
        public void show2(){
            System.out.println("除数异常");
           int num = 5/0;
        }
    }
    
8.2、自定义异常处理:HandlerExceptionResolver
  1. 创建异常处理器类实现HandlerExceptionResolver

    public class MyExceptionResolver implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
            ModelAndView modelAndView = new ModelAndView();   //新建ModelAndView对象用于返回
     
            if (e instanceof ClassCastException){    //如果异常为ClassCastException
                modelAndView.addObject("info","ClassCastException");
                modelAndView.setViewName("error1");
            }else if(e instanceof ArithmeticException){    //如果异常为ArithmeticException
                modelAndView.addObject("info","ArithmeticException");
                modelAndView.setViewName("error2");
            }
            return modelAndView;     //返回模型视图
        }
    }
    
  2. 配置异常处理器

     <bean class="com.zjj.maven.Resolver.MyExceptionResolver"></bean>  <!--自定义异常处理只需要将异常处理类全限定名加入容器即可-->
    
  3. 编写异常页面

    <!--error-->
    <body>
    <p>类型转换异常</p><br>
    ${info}
    </body>
    

    public String show2() throws Exception{
    userService.show2();
    return “index”;
    }
    //类型转换异常
    @RequestMapping(“exception1”)
    public String show1() throws Exception{
    userService.show1();
    return “index”;
    }
    }

    
    - Service
    
    ```java
    public class userService {
         //类型转换异常
        public void show1(){
            System.out.println("类型转换异常");
            Object str = "xxx";
            Integer num = (Integer) str;
        }
         //除数为0异常
        public void show2(){
            System.out.println("除数异常");
           int num = 5/0;
        }
    }
    
8.2、自定义异常处理:HandlerExceptionResolver
  1. 创建异常处理器类实现HandlerExceptionResolver

    public class MyExceptionResolver implements HandlerExceptionResolver {
        @Override
        public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
            ModelAndView modelAndView = new ModelAndView();   //新建ModelAndView对象用于返回
     
            if (e instanceof ClassCastException){    //如果异常为ClassCastException
                modelAndView.addObject("info","ClassCastException");
                modelAndView.setViewName("error1");
            }else if(e instanceof ArithmeticException){    //如果异常为ArithmeticException
                modelAndView.addObject("info","ArithmeticException");
                modelAndView.setViewName("error2");
            }
            return modelAndView;     //返回模型视图
        }
    }
    
  2. 配置异常处理器

     <bean class="com.zjj.maven.Resolver.MyExceptionResolver"></bean>  <!--自定义异常处理只需要将异常处理类全限定名加入容器即可-->
    
  3. 编写异常页面

    <!--error-->
    <body>
    <p>类型转换异常</p><br>
    ${info}
    </body>
    
  4. 测试异常跳转

Mybatis

https://blog.csdn.net/wuraox/article/details/113564687

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java SSMSpring+SpringMVC+MyBatis)是一种基于Java语言的Web开发框架。学习这个框架的过程,我深刻体会到它的强大和灵活性。 首先,Spring框架为开发者提供了一个强大的IOC(Inversion of Control)容器,它能够管理和注入对象,减少了代码之间的耦合性。通过配置文件或注解,我们可以轻松地定义和获取各种对象,提高了代码的可维护性和可扩展性。 其次,SpringMVC框架是一种MVC(Model-View-Controller)设计模式的实现,它用于处理Web请求和响应。通过配置一个请求映射表和处理器,我们可以将请求分发给相应的控制器进行处理,并将处理结果返回给客户端。SpringMVC还提供了一些便捷的注解和标签,用于简化页面的渲染和参数的绑定。 最后,MyBatis是一种优秀的持久化框架,它能够将数据库操作与Java对象之间的映射简化为简单的配置。通过编写SQL映射文件和定义POJO(Plain Old Java Object)类,我们可以方便地进行数据库的增删改查操作,而无需编写冗长的SQL语句。 在学习Java SSM框架的过程,我深入理解了软件开发过程的MVC思想,并学会了如何利用SpringSpringMVC和MyBatis来实现一个完整的Web应用程序。通过不断的实践和调试,我逐渐培养了自己解决问题和调试代码的能力。 总结起来,学习Java SSM框架使我深入理解了软件开发的各个环节,并提升了我的编码能力和开发效率。我相信这些知识和经验将对我的职业发展和项目实施起到积极的促进作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值