Spring相关问题

  • IOC(Inversion of Control):控制反转.
  • DI(Dependency Injection:依赖注入.

正向控制:我们控制依赖,然后交由容器,容器被动接受.

反向控制:容器来控制类与类的依赖关系,我们只负责将类交由容器,不用负责组装类(调整类与类之间的依赖).

控制反转: (是一种概念不是动作)

 在传统项目开发中,我们有容器化管理这个机制,把类交由容器来管理,但是类与类之间会产生依赖关系,我们传统的处理方案是,例如servlet,我们应用程序自己处理完依赖关系之后交由容器,容器只负责调用和执行,但是并不负责管理关系,增加了开发难度,控制反转是将类与类的关系交由容器,应用程序只负责将需要管理关系的类交给容器,管理权限发生转换. 总之~

类与类之间的依赖关系的处理交由容器来负责,应用程序只负责将需要处理的类交由容器即可.

 依赖注入:(是动作) 依赖于容器将原有的依赖关系注入到目标中

        将原本类和类之间的关系,依赖于容器进行添加,来完成最终的组转过程.

 1.自动装配

        一个类里面 创建另一个类当属性的话  在属性上面写@Autowire或者@Resourc自动装配,使用自动装配的前提自动装配的对象的属性在IOC容器中存在 

2.注解开发

@Component

        dao@Repository

        service@service

        controller@Controller

这四个注解的功能是一样的,都是代表将某个类注册到Spring中,装配Bean

3. <context:annotation-config/>和<context:component-scan/>的区别

        < context:annotation-config> 是用于激活那些已经在spring容器里注册过的bean上面的注解,也就是显示的向Spring注册:(以下四个注解)

  1. AutowiredAnnotationBeanPostProcessor

  2. CommonAnnotationBeanPostProcessor

  3. PersistenceAnnotationBeanPostProcessor

  4. RequiredAnnotationBeanPostProcessor

  • 比如我们要使用@Autowired注解,那么就必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。传统声明方式如下:
  • <bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor "/>
  • 如果想使用@ Resource 、@ PostConstruct、@ PreDestroy等注解就必须声明CommonAnnotationBeanPostProcessor。传统声明方式如下
  • <bean class="org.springframework.beans.factory.annotation. CommonAnnotationBeanPostProcessor"/> 
  • 如果想使用@PersistenceContext注解,就必须声明PersistenceAnnotationBeanPostProcessor的Bean。
  • <bean class="org.springframework.beans.factory.annotation.PersistenceAnnotationBeanPostProcessor"/> 
  • 如果想使用 @Required的注解,就必须声明RequiredAnnotationBeanPostProcessor的Bean。
  • <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/> 

    一般来说,像@ Resource 、@ PostConstruct、@Antowired这些注解在自动注入还是比较常用,所以如果总是需要按照传统的方式一条一条配置显得有些繁琐和没有必要,于是spring给我们提供< context:annotation-config/>的简化配置方式,自动帮你完成声明。

  • 总之

  • (1)< context:annotation-config />:仅能够在已经在已经注册过的bean上面起作用。对于没有在spring容器中注册的bean,它并不能执行任何操作。 并且@Component、@Controller、@Service对这些注解无效 所以就出来了以前那个

  • (2)< context:component-scan base-package="XX.XX"/> :除了具有上面的功能之外,还具有自动将带有@component,@service,@Repository等注解的对象注册到spring容器中的功能。 

 4.< mvc:annotation-driven/>

< mvc:annotation-driven /> 是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学都快速应用默认配置方案。 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的。

处理器映射器 处理器适配器

并提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)。

 5.<mvc:default-servlet-handler />

        让springmvc不处理静态资源(.css .js .html .mp3 .mp4)

6.乱码问题(最重要的就是要/*)

 前台传中文 后台变乱码

a.过滤器解决乱码(传统的)

建包(filter->EncodingFilter)        

public class EncodingFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setCharacterEncoding("utf-8");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    public void destroy() {

    }
}

b.springmvc专属的过滤器

<filter>
   <filter-name>encoding</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>encoding</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

c.牛逼人写的过滤器

package com.kuang.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;

/**
* 解决get和post请求 全部乱码的过滤器
*/
public class GenericEncodingFilter implements Filter {

   @Override
   public void destroy() {
  }

   @Override
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
       //处理response的字符编码
       HttpServletResponse myResponse=(HttpServletResponse) response;
       myResponse.setContentType("text/html;charset=UTF-8");

       // 转型为与协议相关对象
       HttpServletRequest httpServletRequest = (HttpServletRequest) request;
       // 对request包装增强
       HttpServletRequest myrequest = new MyRequest(httpServletRequest);
       chain.doFilter(myrequest, response);
  }

   @Override
   public void init(FilterConfig filterConfig) throws ServletException {
  }

}

//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {

   private HttpServletRequest request;
   //是否编码的标记
   private boolean hasEncode;
   //定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
   public MyRequest(HttpServletRequest request) {
       super(request);// super必须写
       this.request = request;
  }

   // 对需要增强方法 进行覆盖
   @Override
   public Map getParameterMap() {
       // 先获得请求方式
       String method = request.getMethod();
       if (method.equalsIgnoreCase("post")) {
           // post请求
           try {
               // 处理post乱码
               request.setCharacterEncoding("utf-8");
               return request.getParameterMap();
          } catch (UnsupportedEncodingException e) {
               e.printStackTrace();
          }
      } else if (method.equalsIgnoreCase("get")) {
           // get请求
           Map<String, String[]> parameterMap = request.getParameterMap();
           if (!hasEncode) { // 确保get手动编码逻辑只运行一次
               for (String parameterName : parameterMap.keySet()) {
                   String[] values = parameterMap.get(parameterName);
                   if (values != null) {
                       for (int i = 0; i < values.length; i++) {
                           try {
                               // 处理get乱码
                               values[i] = new String(values[i]
                                      .getBytes("ISO-8859-1"), "utf-8");
                          } catch (UnsupportedEncodingException e) {
                               e.printStackTrace();
                          }
                      }
                  }
              }
               hasEncode = true;
          }
           return parameterMap;
      }
       return super.getParameterMap();
  }

   //取一个值
   @Override
   public String getParameter(String name) {
       Map<String, String[]> parameterMap = getParameterMap();
       String[] values = parameterMap.get(name);
       if (values == null) {
           return null;
      }
       return values[0]; // 取回参数的第一个值
  }

   //取所有值
   @Override
   public String[] getParameterValues(String name) {
       Map<String, String[]> parameterMap = getParameterMap();
       String[] values = parameterMap.get(name);
       return values;
  }
}

7.Spring让dao接口自动实现(利用反射) 

<?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"
       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">
    <context:property-placeholder location="classpath:database.properties"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <property name="autoCommitOnClose" value="false"/>
        <property name="checkoutTimeout" value="10000"/>
        <property name="acquireRetryAttempts" value="2"/>
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <property name="basePackage" value="com.ZiRuo.dao"/>
    </bean>
   
<!--    <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">-->
<!--        <property name="mapperInterface" value="com.mapper.UserMapper" />-->
<!--        <property name="sqlSessionFactory" ref="sqlSessionFactory" />-->
<!--    </bean>-->
</beans>

你要去生成一个这个接口的实现类你需要几个步骤
1.你需要生成一个具体的实现类
2.你需要实现接口方法
3.你需要在方法里写具体的mybatis代码
首先说(1)
如果你想生成一个接口的实现类,这里的方式有2种:
第一种可以通过动态代理机制,生成这个接口的代理类这个技术我们还没讲,但是在AOP时候就会讲,是一种java的底层机制,利用反射技术实现的。
第二种用的是ASM源代码生成器模式,太复杂一般不用也没意义,Spring里用的就是第一种。
然后说(2)
在动态代理中只有一个方法,它可以代理所有的方法,所以你不用具体去实现某一个方法,
因为对于动态代理来说,他可以一个方法干所有,所以ID里的方法名在这里没什么用
最后说(3)
你生成完的动态代理方法相当于只有一个空壳子,需要知道具体里面写什么代码,常规的mybatis代码
是完全流程化的
String resource = "mybatis-config.xml";
Reader reader = Resources.getResourceAsReader(resource);
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = builder.build(reader);
SqlSession session = sqlSessionFactory.openSession();
//通过session.select|update|delete|.....(sql)来执行SQL语句
最大的区别就是你用的SQL和参数,这时候ID就有用了,ID写的是方法名,其实不是用来生成方法的,
前面说的动态代理可以一个方法代理所有方法,但是不同方法之间虽然流程完全一致,但是SQL不同,
所以你掉了不同方法,他就找这个方法名匹配的SQL传递进去执行,而spring的DI机制目的就是把重复的代码在DI过程中由容器完成
交由我们的是最终一个可以处理这个事情的方法,所以以上说的事都是SPRING干了,然后通过DI注入到Service里一个这样的DAO,你可以用我讲的输出类的方式看看它给SERVICE的DAO对象的实际类的类名,就是那个代理类 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一些常见的 Spring Boot 问题及其答案: 1. 什么是 Spring Boot? Spring Boot 是一个基于 Spring 框架的快速开发框架,帮助开发人员快速创建现代化的、可部署的应用程序。它提供了许多功能,如自动配置、嵌入式 Web 服务器、监控和管理端点等。 2. Spring Boot 的优点是什么? Spring Boot 有以下优点: - 快速开发:Spring Boot 提供了自动配置和快速启动的能力,使开发人员可以快速创建现代化的应用程序。 - 简化配置:Spring Boot 提供了默认配置选项,并支持外部化配置,使开发人员可以轻松配置应用程序。 - 微服务支持:Spring Boot 提供了对微服务架构的支持,并集成了许多常见的微服务组件。 - 可扩展性:Spring Boot 的模块化架构使得应用程序可以轻松扩展,添加新的组件或模块。 3. 如何创建一个 Spring Boot 应用程序? 可以使用 Spring Initializr(https://start.spring.io/)创建一个空的 Spring Boot 应用程序,或者使用 Spring Boot CLI 在命令行中创建。 4. Spring Boot 如何处理依赖? Spring Boot 使用 Maven 或 Gradle 管理依赖项。它提供了许多预定义的依赖项,开发人员可以在项目中添加这些依赖项来轻松地集成常见的功能。 5. 如何运行 Spring Boot 应用程序? 可以使用 Maven 或 Gradle 打包应用程序,并使用 java -jar 命令运行生成的 jar 文件。也可以使用 IDE 中的“运行”按钮启动应用程序。 6. 如何配置 Spring Boot 应用程序? Spring Boot 提供了多种配置方式,包括 application.properties、application.yml 和环境变量等。开发人员可以使用这些配置文件来配置应用程序。 7. 如何使用 Spring Boot 自动配置? Spring Boot 自动配置基于类路径中存在的依赖项来配置应用程序。如果开发人员引入了某个依赖项,Spring Boot 将自动配置相关的功能。如果需要自定义配置,可以通过在应用程序中添加自定义配置类来覆盖默认配置。 8. 如何使用 Spring Boot 集成其他技术? Spring Boot 提供了许多集成其他技术的组件,如 Spring Data、Spring Security、Spring Cloud 等。开发人员可以在项目中添加这些组件来轻松集成其他技术。 9. 如何优化 Spring Boot 应用程序的性能? 可以通过以下方式来优化 Spring Boot 应用程序的性能: - 在生产环境中使用嵌入式容器。 - 避免过多的依赖项。 - 启用缓存。 - 使用合适的日志级别。 - 启用 GZip 压缩。 10. 如何进行 Spring Boot 应用程序的测试? 可以使用 JUnit 或 Spring Test 进行单元测试。Spring Boot 还提供了一些用于测试的工具,如 TestRestTemplate 和 MockMvc。开发人员可以使用这些工具来测试应用程序的不同方面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值