java面试之框架知识整理

  1. Spring3MVC与Struts2MVC比较
    1、SpringMVC支持Restful url,这感觉爽,就开发效率而言高;
    2、SpringMVC基本实现了零配置,配置好Spring的ApplicationContext.xml和web.xml后,基本就不需要其他配置了。而且Spring的配置也相对简单。而struts2就不行了,需要的配置相对比较多,也比较复杂;
    3、SpringMVC对每次请求是方法级的拦截,拦截到方法后根据参数上的注解,将request数据注入。一个方法对应一个request请求,并且SpringMVC方法之间是相互独立的,独享request和response数据。而StrutsMVC是类级别的拦截,每次请求来了就创建一个action,然后调用getter、setter方法。一个Action对应一个request上下文。
    4、让人更爽的是SpringMVC知识JSR303,处理ajax的请求更加方面,只需要注解一个@ResponseBody,然后直接返回相应文件即可。

  2. SpringMVC的工作流程描述:
    1.用户向服务器发送请求, 请求被Spring前端控制Servlet DispatcherServlet所捕获;
    2.DispatcherServlet对请求的URL进行解析,得到资源标识符.根据URI调用HandlerMapping获得该Handler配置的所有相关对象,最后以HandlerExecutionChain对象的形式返回;
    3.DispatcherServlet根据获得的Handler选择一个合适的HandlerAdapter;
    4.提取Request中的模型数据, 填充Handler入参,执行Controller,根据配置做一些额外的工作: 比如数据转换和验证;
    5.Handler执行完成后, 向DispatcherServlet返回一个ModelAndView对象;
    6.根据返回的ModelAndView,选择一个合适的ViewResolver返回给DispatcherServlet;
    7.ViewResolver结合Model和View来渲染视图;
    8.将视图返回给客户端.

  3. Struts2的工作原理:
    1.客户端初始化一个指向Servlet容器的请求;
    2.这个请求经过一系列过滤器, Filter;
    3.接着StrutsPrepareAndExecuteFilter被调用, StrutsPrepareAndExecuteFilter询问ActionMapper来决定是否需要调用某个Action;
    4.如果ActionMapper决定调用某个Action, StrutsPrepareAndExecuteFilter把请求的处理交给ActionProxy;

    1. ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类;
    2. ActionProxy创建一个ActionInvocation的实例;
    3. ActionInvocation实例使用命名模式来调用, 在调用Action的过程前后, 涉及到相关拦截器的调用;
      8.一旦Action执行完毕, ActionInvocation负责根据struts.xml中的配置找到对应的返回结果, 这个结果通常是一个需要被表示的JSP或者FreeMarker的模板.
  4. Spring MVC:
    一:配置阶段:
    1.配置web.xml—DispatcherServlet;
    2.设定init-param——contextConfigLocation=classpath:application…properties;
    3.设定url-pattern——/*;
    4.配置Annotation——@Controller @Service @Autowired @RequestMapping

    二:初始化阶段:

1.调用init()方法—加载配置文件;

2.扫描相关的类——scan-package=”com.gupaodu”;

3.IOC容器初始化——Map;
4.创建实例并保存至容器——通过反射机制将类实例化放入IOC容器中;

5.进行DI操作——扫描IOC容器中的实例,给没有赋值的属性自动赋值;

6.初始化HandlerMapping——将一个URL和一个Method进行一对一的关联映射Map;

三:运行阶段:

1.调用doPost()/doGet()——Web容器调用doPost/doGet方法,获得request/response对象;
2.匹配HndlerMapping——从request对象中获得用户输入的url,找到其对应的Method;
3.反射调用method.invoke()——利用反射调用方法并返回结果;
4.Response.getWrite().write()——将返回结果输出到浏览器。
5. 请用自己的语言描述SpringIOC、DI、MVC的基本执行原理
SpringIOC, 控制反转(Inversion of Control),将spring中所有Bean的控制权(创建、消费、管理)交给SpringIOC容器,整个过程包括三个步骤:
①加载配置文件
通过io流读取配置文件,并存入property对象中
③扫描相关的类
通过scan-package属性指定扫描文件夹,遍历指定文件夹下的所有类文件,找出文件名称(排除非.class类型文件),保存到文件名列表
④初始化IOC容器,将扫描到的相关的类实例化,保存到IOC容器中
类似于Map键值对集合,遍历文件名称列表通过反射实例化对象(类必须有类似Controller、service注解的才能去实例化),并保存到Map集合中
key取值有三种情况:
1)在多个包下出现相同类名,通过一种有效方式使其不同
2)默认的类名首字母小写
3)如果是接口,判断实现类个数,如果只有一个,默认选择这个实现类,如果多个,只能抛出异常
DI,依赖注入(Dependency Injection)
Spring 不仅保存了自己创建的对象,而且保存了对象与对象之间的关系,扫描IOC容器中的实例,找出实例的所有属性,如果有autowired注解,就在IOC容器中通过名字找到对应之前保存的对象,设置属性.
MVC M是返回的数据,V是ModeView解析给客户端返回的视图,C是Control相关的逻辑处理
存储url和类方法的键值对集合,客户端可以通过url找到对应的类方法,
通过反射机制,执行该方法并返回数据给客户端.
遍历IOC容器Map,找出含有注解为Controler的对象的所有方法,如果有类似RequestMapping注解,则获取url(clazz.getAnnotation的RequestMapping中的url+method.getAnnotation的RequestMapping中的url)值,并把以url作为key,method作为value的集合保存到HandlerMapping中,当客户端通过url匹配到HandlerMapping集合中的某个方法时,通过反射调用并返回数据视图给客户端.
6. 软件设计的基本原则:

  1. 设计模式:

  2. Spring中的编程思想:
    OOP: 面向对象编程(封装,继承,多态,一切皆对象),用程序来描述生活中一切事物(需求转换为代码实现).
    BOP: 面向Bean编程,Java本身就是一种面向对象的编程,用一个个的Bean来体现.
    不需要new Bean,只需要你声明,只需要关注bean和bean之间的联系.
    AOP编程:解耦,专人做专事, 面向切面编程:找出多个bean中有一定规律的代码,开发时将其拆开,运行时再将其合并,面向切面编程就是面向规则编程.日志监控;事务开启,关闭;权限认证,统一错误管理, 自动缓存处理.
    切面: 面向规则,具有相同规则的方法的集合体;
    通知: 回调;
    切入点: 需要代理的具体方法;
    目标对象: 被代理的对象;
    AOP代理: 主要有两种JDK和CGLib;
    前置通知: 在invoke Pointcut之前调用;
    后置通知: Pointcut之后调用, 织入的方法;
    返回后通知: 返回值为Void, 织入的方法;
    环绕通知: 只要触发调用, 织入的方法;
    异常通知: Pointcut抛出异常.
    a. Aspect(切面),通常是一个类,里面可以定义切入点和通知;
    b. JoinPoint(连接点),程序执行过程中明确的点,一般是方法的调用;
    c. Advice(通知):Aop在特定的切入点上执行的增强处理;
    d. Pointcut(切入点),就是带有通知的连接点,在程序中主要体现为书写切入点表达式;增强同一规律的方法.
    IoC:控制反转:控制权反转,把创建对象的控制权反转给Spring(BeanFactory)DI:  依赖注入,依赖查找,自动赋值,三种赋值方法:构造方法, set赋值,直接赋值(反射,暴力强吻).(@Autowired private Object object; @Resource(“bean”) public void setName(){} )
    事务用法:
    原子性:要么全部完成, 要么全部不起作用;
    一致性: 使一个一致性状态变成另一个一致性状态;
    隔离性: 一个事务的执行不能被另一个事务干扰;
    持久性: 事务一旦被提交, 它对数据库中数据的改变就是永久性的.

  3. Spring中的设计模式:
    工厂模式: 只对结果负责, 封装创建过程.(BeanFactory, Calender)
    单例模式:保证独一无二.(ApplicationContext, Calender)
    原型模式:拔一根猴毛,吹出千万根.(ArrayList[extends Cloneable], PrototypeBean)
    代理模式:找人办事增强职责.(ProxyFactoryBean, CglibAopProxy)
    委派模式:干活算你的(普通员工),功劳算我的(项目经理).(DispatcherServlet)
    策略模式:用户选择, 结果统一.(InstantiationStrategy)
    模板模式:流程标准化,自己实现定制.(jdbcTemplate, HttpServlet)
    适配器模式:兼容转换头.(AdvisorAdapter, HandlerAdapter)
    装饰器模式:他大舅他二舅都是他舅.(BufferedReader)
    观察者模式:广播, 任务完成时通知.(ContextLoaderListener)

  4. Spring框架能给我们带来哪些好处:

  5. 简化开发:
    a) DI:使得JavaBean之间的依赖关系一目了然;
    b) IOC:帮助我们管理好系统中的Bean,分阶段,分层次系统地管理,性能提高了;

  6. 万能胶:能够兼容市面上很多成熟的框架:比如Struts,MyBatis,Quartz,Timer,Shiro,Data

  7. 模块化设计:将包和类通过不同的模块完整的隔离开来,能够在使用的时候即插即用,按需分配;比如插件的引用,用哪个就引用哪个;

  8. 自带测试组件:JUnit;

  9. Web MVC:支持的非常合理,过度设计的嫌疑(Struts中Form和Action对应出现, Spring只需要Bean和Attribute不需要Form),完美分离了Servlet和普通的Bean的关联关系;

  10. 声明式事务:将非功能性代码和功能性代码分离,提出了事务管理提前声明,通过不同的切面实现不同的切面模型,大大提高了维护成本。

  11. BeanFactory和ApplicationContext的区别:

  12. ApplicationContext是BeanFactory的子接口: getBean();1.IOC容器中的Bean监控,生命周期;

  13. 支持国际化i18n;

  14. 拓展了统一资源文件读取方式URL,可以是一个本地的URL,也可以是一个网络URL,ClassPathXmlApplicationContext从ClassPath的XML中配置文件中读取上下文,生成上下文定义,即指的是程序运行的环境;
    FileSystemXmlApplicationContext,由文件系统中的XML配置文件读取上下文;
    XmlWebApplicationContext由Web应用的XML文件读取上下文;,
    AnnotationConfigApplicationContext使用他可以实现基于Java的配置类加载Spring应用的上下文,避免使用application.xml进行配置,相比XML配置来说更加敏捷。

  15. Spring Bean的生命周期:

  16. 初始化之后的回调:initializingBean;
    销毁之前的回调:DisposableBean;

  17. init()和destroy();

  18. 通过注解:@PostConstruct和@PreDestroy

  19. Spring Bean各作用域之间的区别:
    总共5个范围,对象何时创建,何时销毁:

  20. prototype: 为每一个Bean请求提供一个实例:【顶层1岁】

  21. singleton: 默认的,单例模式由Bean Factory自身来维护,跟spring同生共死;【顶层100岁】

  22. request: 用户发出请求的时候request出生【Web层10岁】

  23. session:确保每个session中有一个Bean实例,session过期Bean自然失效【Web层20岁】;

  24. globel-session Context:【80岁】

  25. Spring中的Bean是线程安全的吗:
    Spring中的Bean是由IOC容器来创建的,而创建的对象是自己定义的,BeanDefinition->BeanWrapper->Class.newInstance()->Map做了一次代理,用一个新的类代替了原来的类。所以跟我们写的代码有关系,跟Spring无关的。

  26. MVC是什么?:
    MVC是Model—View—Controler的简称。即模型—视图—控制器。MVC是一种设计模式,它强制性的把应用程序的输入、处理和输出分开。MVC中的模型、视图、控制器它们分别担负着不同的任务。
    视图: 视图是用户看到并与之交互的界面。视图向用户显示相关的数据,并接受用户的输入。视图不进行任何业务逻辑处理。
    模型: 模型表示业务数据和业务处理。相当于JavaBean。一个模型能为多个视图提供数据。这提高了应用程序的重用性
    控制器: 当用户单击Web页面中的提交按钮时,控制器接受请求并调用相应的模型去处理请求。 然后根据处理的结果调用相应的视图来显示处理的结果。
    MVC的处理过程:首先控制器接受用户的请求,调用相应的模型来进行业务处理,并 返回数据给控制器。控制器调用相应的视图来显示处理的结果。并通过视图呈现给用户。
    MVC 缺点:
    (1)增加了系统结构和实现的复杂性。
    (2)视图与控制器间的过于紧密的连接。
    (3)视图对模型数据的低效率访问。
    (4) 目前,一般高级的界面工具或构造器不支持MVC 模式。
    MVC 优点:
    (1)将用户显示(视图)从动作(控制器)中分离出来,提高了代码的重用性。
    (2)实现一个模型的多个视图;采用多个控制器;当模型改变时,所有视图将自动刷新;所有的控制 器将相互独立工作。(3)它还有利于软件工程化管理。
    为什么要用MVC:

  27. 优点:降低耦合度、增强内聚性。

  28. 使人员职能分工明确,有助于团队开发

  29. 有助于分布式开发。4. 封装分解系统的复杂性

  30. Struts2框架?:
    定义: Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。
    底层执行过程:

  31. Struts1和Struts2框架的区别?:
    1.Action方面: 前者继承一个抽象基类, 后者的Action可以实现接口, 也可以实现其他接口, 也可以不实现任何接口,继承ActionSupport类;
    2.线程模式方面: 前者的Action与Servlet API是紧耦合的, 后者不依赖于Servlet容器;
    3.输入捕获:前者使用ActionForm对象捕获输入, 后者直接使用Action属性作为输入属性;
    4.表达式语言: 前者整合了JSTL使用他的EL;后者支持OGNL;
    5.数据校验方面: 前者支持在ActionForm的validate方法中手动校验;后者通过validate方法和XWork校验框架(拦截器机制)来进行校验;
    6.前者所有模块中的Action必须共享相同的生命周期单例; 后者支持通过堆栈为每一个Action创建不同的生命周期,多例;

  32. Spring事务的特性:
    原子性:要么全部完成, 要么全部不起作用;
    一致性: 使一个一致性状态变成另一个一致性状态;
    隔离性: 一个事务的执行不能被另一个事务干扰;
    持久性: 事务一旦被提交, 它对数据库中数据的改变就是永久性的.

  33. Spring的常用注解:
    Spring部分
    1、声明bean的注解
    @Component 组件,没有明确的角色
    @Service 在业务逻辑层使用(service层)
    @Repository 在数据访问层使用(dao层)
    @Controller 在展现层使用,控制器的声明(C)
    2、注入bean的注解
    @Autowired:由Spring提供
    @Inject:由JSR-330提供
    @Resource:由JSR-250提供
    都可以注解在set方法和属性上,推荐注解在属性上(一目了然,少写代码)。
    3、java配置类相关注解
    @Configuration 声明当前类为配置类,相当于xml形式的Spring配置(类上)
    @Bean 注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式(方法上)
    @Configuration 声明当前类为配置类,其中内部组合了@Component注解,表明这个类是一个bean(类上)
    @ComponentScan 用于对Component进行扫描,相当于xml中的(类上)
    @WishlyConfiguration 为@Configuration与@ComponentScan的组合注解,可以替代这两个注解
    4、切面(AOP)相关注解
    Spring支持AspectJ的注解式切面编程。
    @Aspect 声明一个切面(类上)
    使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。
    @After 在方法执行之后执行(方法上)
    @Before 在方法执行之前执行(方法上)
    @Around 在方法执行之前与之后执行(方法上)
    @PointCut 声明切点
    在java配置类中使用@EnableAspectJAutoProxy注解开启Spring对AspectJ代理的支持(类上)
    5、@Bean的属性支持
    @Scope 设置Spring容器如何新建Bean实例(方法上,得有@Bean)
    其设置类型包括:
    Singleton (单例,一个Spring容器中只有一个bean实例,默认模式),
    Protetype (每次调用新建一个bean),
    Request (web项目中,给每个http request新建一个bean),
    Session (web项目中,给每个http session新建一个bean),
    GlobalSession(给每一个 global http session新建一个Bean实例)
    @StepScope 在Spring Batch中还有涉及
    @PostConstruct 由JSR-250提供,在构造函数执行完之后执行,等价于xml配置文件中bean的initMethod
    @PreDestory 由JSR-250提供,在Bean销毁之前执行,等价于xml配置文件中bean的destroyMethod
    6、@Value注解
    @Value 为属性注入值(属性上)
    支持如下方式的注入:
    》注入普通字符

》注入操作系统属性

》注入表达式结果

》注入其它bean属性

》注入文件资源

》注入网站资源

》注入配置文件

注入配置使用方法:
① 编写配置文件(test.properties)
book.name=《三体》
② @PropertySource 加载配置文件(类上)③

还需配置一个PropertySourcesPlaceholderConfigurer的bean。
7、环境切换
@Profile 通过设定Environment的ActiveProfiles来设定当前context需要使用的配置环境。(类或方法上)
@Conditional Spring4中可以使用此注解定义条件话的bean,通过实现Condition接口,并重写matches方法,从而决定该bean是否被实例化。(方法上)
8、异步相关
@EnableAsync 配置类中,通过此注解开启对异步任务的支持,叙事性AsyncConfigurer接口(类上)
@Async 在实际执行的bean方法使用该注解来申明其是一个异步任务(方法上或类上所有的方法都将异步,需要@EnableAsync开启异步任务)
9、定时任务相关
@EnableScheduling 在配置类上使用,开启计划任务的支持(类上)
@Scheduled 来申明这是一个任务,包括cron,fixDelay,fixRate等类型(方法上,需先开启计划任务的支持)
10、@Enable*注解说明
这些注解主要用来开启对xxx的支持
@EnableAspectJAutoProxy 开启对AspectJ自动代理的支持
@EnableAsync 开启异步方法的支持
@EnableScheduling 开启计划任务的支持
@EnableWebMvc 开启Web MVC的配置支持
@EnableConfigurationProperties 开启对@ConfigurationProperties注解配置Bean的支持
@EnableJpaRepositories 开启对SpringData JPA Repository的支持
@EnableTransactionManagement 开启注解式事务的支持
@EnableTransactionManagement 开启注解式事务的支持
@EnableCaching 开启注解式的缓存支持
11、测试相关注解
@RunWith 运行器,Spring中通常用于对JUnit的支持

@ContextConfiguration 用来加载配置ApplicationContext,其中classes属性用来加载配置类

SpringMVC部分
@EnableWebMvc 在配置类中开启Web MVC的配置支持,如一些ViewResolver或者MessageConverter等,若无此句,重写WebMvcConfigurerAdapter方法(用于对SpringMVC的配置)。
@Controller 声明该类为SpringMVC中的Controller
@RequestMapping 用于映射Web请求,包括访问路径和参数(类或方法上)
@ResponseBody 支持将返回值放在response内,而不是一个页面,通常用户返回json数据(返回值旁或方法上)
@RequestBody 允许request的参数在request体中,而不是在直接连接在地址后面。(放在参数前)
@PathVariable 用于接收路径参数,比如@RequestMapping(“/hello/{name}”)申明的路径,将注解放在参数中前,即可获取该值,通常作为Restful的接口实现方法。
@RestController 该注解为一个组合注解,相当于@Controller和@ResponseBody的组合,注解在类上,意味着,该Controller的所有方法都默认加上了@ResponseBody。
@ControllerAdvice 通过该注解,我们可以将对于控制器的全局配置放置在同一个位置,注解了@Controller的类的方法可使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上,
这对所有注解了 @RequestMapping的控制器内的方法有效。
@ExceptionHandler 用于全局处理控制器里的异常
@InitBinder 用来设置WebDataBinder,WebDataBinder用来自动绑定前台请求参数到Model中。
@ModelAttribute 本来的作用是绑定键值对到Model里,在@ControllerAdvice中是让全局的@RequestMapping都能获得在此处设置的键值对。

@Component
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注
@Repository
用于标注数据访问组件,即DAO组件
@Controller
标识一个该类是Spring MVC controller处理器,用来创建处理http请求的对象.
@RestController
Spring4之后加入的注解,原来在@Controller中返回json需要@ResponseBody来配合,如果直接用@RestController替代@Controller就不需要再配置@ResponseBody,默认返回json格式。
@Service
用于标注业务层组件,说白了就是加入你有一个用注解的方式把这个类注入到spring配置中
@Autowired
用来装配bean,都可以写在字段上,或者方法上。
默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,例如:@Autowired(required=false)
@RequestMapping
类定义处: 提供初步的请求映射信息,相对于 WEB 应用的根目录。
方法处: 提供进一步的细分映射信息,相对于类定义处的 URL。
@RequestParam
用于将请求参数区数据映射到功能处理方法的参数上
@Cacheable
用来标记缓存查询。可用用于方法或者类中,当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。
@Resource
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。
@PostConstruct
用来标记是在项目启动的时候执行这个方法。用来修饰一个非静态的void()方法
也就是spring容器启动时就执行,多用于一些全局配置、数据字典之类的加载
被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次
PostConstruct在构造函数之后执行,init()方法之前执行。PreDestroy()方法在destroy()方法执行执行之后执行
@PreDestroy
被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,
类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前
@Qualifier
当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,
在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。
@ComponentScan
默认是代表进行扫描当前包
含有两个参数:
basePackages:可以扫描多个包,是一个数组类型,可能会造成产生多个Bean实例
basePackageClasses:可以扫描多个方法,是一个数组类型,可能会造成产生多个Bean实例
@Scope
用来配置 spring bean 的作用域,它标识 bean 的作用域。
默认值是单例
1、singleton:单例模式,全局有且仅有一个实例
2、prototype:原型模式,每次获取Bean的时候会有一个新的实例
3、request:request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效
4、session:session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效
5、global session:只在portal应用中有用,给每一个 global http session 新建一个Bean实例。
20. MyBatis与Hibernate的区别:
相同点:
1. 针对简单逻辑,Hibernate和MyBatis都有相应的代码生成工具,可以生成简单基本的DAO层方法;
2.Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。

  1. 最大区别: 针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于业务流程。

  2. 开发难度对比: Hibernate的开发难度要大于Mybatis。主要由于Hibernate比较复杂、庞大,学习周期较长。而Mybatis则相对简单一些,并且Mybatis主要依赖于sql的书写,让开发者感觉更熟悉。缺点就是框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
    3 数据库扩展性比较: Mybatis由于所有SQL都是依赖数据库书写的,所以扩展性,迁移性比较差。Hibernate与数据库具体的关联都在XML中,所以HQL对具体是用什么数据库并不是很关心。
    总结:
    mybatis:小巧、方便、高效、简单、直接、半自动
    hibernate:强大、方便、高效、复杂、绕弯子、全自动

  3. MyBatis框架:
    (1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。
    (2)MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
    (3)通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。
    优点:
    JDBC连接数据库会出现代码重复,资源管理,结果集处理,SQL耦合等问题。
    ORM框架能够很好的解决这些问题。
    Hibernate自动生成SQL,基于SQL去做一些优化比较困难。不够灵活
    Mybatis半自动化,主要解决SQL和对象映射问题。
    MyBatis是一个半自动的ORM框架。它解决了如下问题:
    (1)避免执行SQL操作时的重复代码。
    (2)对连接池资源进行统一封装。
    (3)对资源的释放关闭等进行统一封装。
    (4)对数据库操作的常规步骤使用模板模式进行封装。
    (5)对数据库的入参、出参转换进行封装。
    (6)支持缓存。
    (7)支持SQL、出入参的转换映射可配置化。
    (8)支持四大组件的添加拦截器。
    (9)对一些组件,像日志、statement进行了代理增强等。

MyBatis框架的缺点:
(1)SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
(2)SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
JDBC编程有哪些不足之处,Mybatis是如何解决这些问题的?
jdbc连接数据库,会对每一次的连接创建一个线程,使用完毕后关闭线程,频繁的操作会造成系统资源的浪费从而影响性能
在mybatis的配置文件中配置数据库连接池
jdbc的sql语句写在代码中造成代码不易维护 sql变动需要改变Java代码
mybatis将sql语句配置在mapper.xml文件中与Java代码分离 也可以接口映射(约定大于配置)
jdbc的sql语句传参比较麻烦 sql语句的where条件不一定 占位符和参数一一对应
mybatis会自动将Java对象映射至sql语句
jdbc对结果集解析比较麻烦 需要使用游标将结果集一条一条的遍历出来
mybatis自动将sql执行结果映射到Java对象
22. 基于Spring JDBC手写定制自己的ORM框架:
1.加载驱动 Class.forName(驱动名)
2.建立连接 DriverManager.getConnection(URL,用户名,密码)
3.根据传入的对象获取对象实例 Class clazz = obj.getClass();
4.通过反射获取对象注解@Table表名,@Column列名(
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields){
field.setAccessible(true);
if(field.isAnnotationPresent(Column.class)){
Column column = field.getAnnotation(Column.class);}})
5.维护实体属性名和列名映射关系。
6.实体属性名和列名组装sql
7.创建语句集 connection.prepareStatement(sql)
8.判断是否开启事务
9.执行语句集 prepareStatement.executeQuery(sql)
10.获取结果集 ResultSet
11.处理结果集,根据实体属性名和列名将结果集组装成对象.
12.如果有事务,提交事务
13.关闭结果集,关闭语句集,关闭连接

  1. MyBatis源码中用到了哪些设计模式?
    1.工厂模式:SqlSessionFactory, ObjectFactory, DataSourceFactory, TransactionFactory, ReflectorFactory;
    2.建造者模式:SqlSessionFactoryBuilder, XMLConfigBuilder, XMLMapperBuilder, XMLStatementBuilder, CacheBuilder;
    3.代理模式: MapperProxy, Plugin, PooledConnection, ConnectionLogger, ResultSetLogger, StatementLogger, PreparedStatementLogger;
    4.模板方法模式: AttributeValueTemplate, CallTemplate;
    5.适配器模式: ComponentAdapter, ContainerAdapter, BeanAdapter;
    6.单例模式: LogFactory;
    7.享元模式: MapperRegistry, TypeHandlerRegistry, TypeAliasRegistry;
    8.策略模式: DataSource, 还有根据MappedStatement里面的statementType决定StatementHandler的类型;
    9.装饰器模式: LRUCache;
    10.解释器模式: ParameterExpression.

  2. Statement和PrepareStatement的区别:
    1.两个都是接口, PrepareStatement是继承自Statement的;

    1. Statement处理静态SQL, PrepareStatement主要用于执行带参数的语句;
    2. PrepareStatement的addBatch()方法一次性发送多个查询给数据库;
    3. PrepareStatement对SQL只编译了一次(对语句进行了缓存, 相当于一个函数);
    4. PrepareStatement可以防止SQL注入;
  3. #和KaTeX parse error: Expected 'EOF', got '#' at position 6: 的区别: #̲{}是预编译处理,{}是字符串替换.
    Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
    Mybatis在处理 时 , 就 是 把 {}时,就是把 {}替换成变量的值。
    使用#{}可以有效的防止SQL注入,提高系统安全性。
    总结:
    1.是否能防止SQL注入: $方式不会对符号转义, 不能防止SQL注入;
    2.性能方面: KaTeX parse error: Expected 'EOF', got '#' at position 20: …预编译, 不会缓存; 3.能用#̲号的地方尽量用#号; 4.常量….

  4. XML中怎样使用特殊字符:
    1.转义<<(大于可以直接写);
    2.使用–当XML遇到这种格式就会把[]里面的内容原样输出, 不进行解析.

  5. 通用Mapper可以解决哪些问题:
    1.每个Mapper接口中大量的重复方法的定义;
    2.屏蔽数据库的差异;
    3.提供批量操作的方法;
    4.实现分页.

  6. 用注解还是用xml配置:
    常用注解: @Insert, @Select, @Update, @Delete, @Param, @Results, @Result
    在MyBatis的工程中,我们有两种配置SQL的方式,一种是在Mapper.xml中集中管理, 一种是在Mapper接口上,用注解方式配置SQL: 注解的缺点是SQL无法集中管理, 复杂的SQL很难配置. 所以建议在业务复杂的项目中只使用XML配置的形式,业务简单的项目中可以使用注解和XML混用的形式.

  7. association和collection的区别:
    association是用于一对一和多对一,
    而collection是用于一对多的关系.

  8. 一对一关联查询的几种配置方式:

  9. 当实体类中的属性名和表中的字段名不一样 ,怎么办 :
    第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
    第2种: 通过来映射字段名和实体类属性名的一一对应的关系。

  10. 在mapper中如何传递多个参数?

  11. Mybatis动态sql有什么用?执行原理?有哪些动态sql?
    Mybatis动态sql可以在Xml映射文件内,以标签的形式编写动态sql,
    执行原理是根据表达式的值 完成逻辑判断并动态拼接sql的功能。
    Mybatis提供了9种动态sql标签:
    trim(替换) | where (where条件的追加)| set(用于修改多个列) | foreach(循环结果集) | if(判断) | choose | when | otherwise (相当于Java中的if(){}else{} 两者选其一)| bind。

  12. Xml映射文件中,除了常见的select|insert|update|delete标签之外,还有哪些标签?
    (结果集映射)、、、、(生成主键),
    加上动态sql的9个标签,其中为sql片段标签,通过标签引入sql片段,为不支持自增的主键生成策略标签。
    35.Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
    不同的Xml映射文件,如果配置了namespace,那么id可以重复;
    如果没有配置namespace,那么id不能重复;
    原因: namespace+id是作为Map的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。
    但是,在以前的Mybatis版本的namespace是可选的,不过新版本的namespace已经是必须的了。
    36.一对一关联查询和一对多关联查询:

37.一对一关联查询有几种方式?
有联合查询和嵌套查询,联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;
嵌套查询是先查一个表,根据这个表里面的结果的 外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。
38. Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
它的原理是: 使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。
当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的.
39. Mybatis的一级、二级缓存:
1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;
3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear 掉并重新更新,如果开启了二级缓存,则只根据配置判断是否刷新。
40. 什么是MyBatis的接口绑定?有哪些实现方式?
接口绑定,就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定, 我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。
接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定;另外一种就是通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。当Sql语句比较简单时候,用注解绑定, 当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多。
41、使用MyBatis的mapper接口调用时有哪些要求?
① Mapper接口方法名和mapper.xml中定义的每个sql的id相同;
② Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同;
③ Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同;
④ Mapper.xml文件中的namespace即是mapper接口的类路径。
42.简述Mybatis的插件运行原理,以及如何编写一个插件。
Mybatis采用责任链模式,通过动态代理组织多个插件(拦截器),
通过这些插件可以改变Mybatis的默认行为(诸如SQL重写之类的).
• Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
• ParameterHandler (getParameterObject, setParameters)
• ResultSetHandler (handleResultSets, handleOutputParameters)
• StatementHandler (prepare, parameterize, batch, update, query)
总体概括为:
• 拦截执行器的方法
• 拦截参数的处理
• 拦截结果集的处理
• 拦截Sql语法构建的处理

Mybatis的插件是采用对四大接口的对象生成动态代理对象的方法来实现的。
Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。
编写插件:实现Mybatis的Interceptor接口并复写intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。
43.Mybatis是否可以映射Enum枚举类?
Mybatis可以映射枚举类,不单可以映射枚举类,Mybatis可以映射任何对象到表的一列上。映射方式为自定义一个TypeHandler,实现TypeHandler的setParameter()和getResult()接口方法。TypeHandler有两个作用,一是完成从javaType至jdbcType的转换,二是完成jdbcType至javaType的转换,体现为setParameter()和getResult()两个方法,分别代表设置sql问号占位符参数和获取列查询结果。
44.mybatis编程步骤是什么样的?
1.创建SqlSessionFactory:
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
2.通过SQLSessionFactory创建SqlSession
SqlSession openSession = sqlSessionFactory.openSession();
3、通过sqlsession执行数据库操作
4、调用session.commit()或session.rollback()
5、调用session.close()关闭会话
45. Hibernate工作原理及为什么要用?:

  1. 读取并解析配置文件: 通过Configuration config = new Configuration().configure();
  2. 读取并解析映射信息,创建SessionFactory: 由hibernate.cfg.xml中的; 通过SessionFactory sf = config.buildSessionFactory();
  3. 打开Sesssion: Session session = sf.openSession();
  4. 创建事务Transation: Transaction tx = session.beginTransaction();
  5. 持久化操作: persistent operate操作数据
  6. 提交事务: tx.commit();
  7. 关闭Session
  8. 关闭SesstionFactory
    使用Hibernate框架就不用我们写很多繁琐的SQL语句。
    Hibernate实现了ORM-Object Relational Mapping,能够将对象映射成数据库表,从而简化我们的开发!
    Hibernate中对象的状态:临时/瞬时状态(new); 持久化状态(受Session管理进行CRUD操作之后在数据库中存在); 游离状态(Session关闭, 在数据库中存在).
    Hibernate的查询方式: 对象导航查询(objectcomposition); HQL查询(1、 属性查询; 2、 参数查询、命名参数查询; 3、 关联查询; 4、 分页查询; 5、 统计函数); Criteria 查询; SQLQuery本地SQL查询;
    什么是SessionFactory: SessionFactory 是Hibrenate单例数据存储和线程安全的,以至于可以多线程同时访问。一个SessionFactory 在启动的时候只能建立一次。SessionFactory应该包装各种单例以至于它能很简单的在一个应用代码中储存.
    hibernate 优缺点
    ①. 优点:

对 JDBC 访问数据库的代码做了封装,简化了数据访问层繁琐的重复性代码
映射的灵活性, 它支持各种关系数据库, 从一对一到多对多的各种复杂关系.
非侵入性、移植性会好
缓存机制: 提供一级缓存和二级缓存
②. 缺点:
无法对 SQL 进行优化
框架中使用 ORM原则, 导致配置过于复杂
执行效率和原生的JDBC 相比偏差: 特别是在批量数据处理的时候
不支持批量修改、删除

  1. SpringBoot:
    微服务是一种软件架构设计理念,微服务是一种分布式系统架构,是一种思想,是一种设计原则。spring boot是javaee领域里实现微服务的一种技术实现.
    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的创建、运行、调试、部署等。用来简化spring应用的初始搭建以及开发过程 使用特定的方式来进行配置(properties或yml文件) ;
    使用Spring Boot可以做到专注于Spring应用的开发,而无需过多关注XML的配置。 Spring Boot使用“习惯优于配置”的理念,简单来说,它提供了一堆依赖打包,并已经按照使用习惯解决了依赖问题。使用Spring Boot可以不用或者只需要很少的Spring配置就可以让企业项目快速运行起来。它是对”约定优于配置”这个理念下的最佳实践, 它是一个服务于框架的框架, 服务的范围是简化配置文件.
    Spring Boot 在简化配置、打包和集成第三方工具方面确实做得很好,可以减低 Spring 开发人员的入门门槛。这样带来的好处就是降低开发人员对于框架的关注点,可以把更多的精力放在自己的业务代码上。
    约定优于配置的体现:
    1.maven的目录结构: 默认有resources文件夹存放配置文件; 默认的打包方式为jar;
    2.spring-boot-starter-web默认包含spring-mvc相关依赖以及内置的tomcat容器;
    3.默认提供application.properties/yml文件;
    4.spring.profiles.active属性决定运行时读取的配置文件;
    5.EnableAutoConfiguration默认对于依赖的starter进行自动装载.
    核心功能:
    1、 可独立运行的Spring项目:Spring Boot可以以jar包的形式独立运行。
    2、 内嵌的Servlet容器:Spring Boot可以选择内嵌Tomcat、Jetty或者Undertow,无须以war包形式部署项目。
    3、 简化的Maven配置:Spring提供推荐的基础 POM 文件来简化Maven 配置。
    4、 自动配置Spring:Spring Boot会根据项目依赖来自动配置Spring 框架,极大地减少项目要使用的配置。
    5、 提供生产就绪型功能:提供可以直接在生产环境中使用的功能,如性能指标、应用信息和应用健康检查。
    6、 无代码生成和xml配置:Spring Boot不生成代码。完全不需要任何xml配置即可实现Spring的所有配置。

com.example.myproject 目录下:
• Application.java:建议放到根目录下面,是项目的启动类,Spring Boot 项目只能有一个 main 方法。
• comm:目录建议放置公共的类,如全局的配置文件、工具类等。
• domain:目录主要用于实体(Entity)与数据访问层(Repository)。
• repository:数据库访问层代码。
• service:该层主要是业务类代码。
• web:该层负责页面访问控制。
resources 目录下:
• static:目录存放 Web 访问的静态资源,如 JS、CSS、图片等。
• templates:目录存放页面模板。
• application.properties:项目的配置信息。
test 目录存放单元测试的代码;pom.xml 用于配置项目依赖包,以及其他配置。
采用默认配置可以省去很多设置,当然也可以根据自己的喜好来进行更改。最后,启动 Application main 方法,至此一个 Java 项目搭建好了!

什么是YAML?
YAML是一种人类可读的数据序列化语言。它通常用于配置文件。 与属性文件相比,如果我们想要在配置文件中添加复杂的属性,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。
springboot自动配置的原理 :
在spring程序main方法中 添加@SpringBootApplication或者@EnableAutoConfiguration 会自动去maven中读取每个starter中的spring.factories文件 该文件里配置了所有需要被创建spring容器中的bean.
springboot读取配置文件的方式:
springboot默认读取配置文件为application.properties或者是application.yml;
Spring Boot 的核心注解是哪个?它主要由哪几个注解组成的?
启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:
@SpringBootConfiguration:组合了 @Configuration 注解它是JavaConfig形式的基于SpringIoC容器的配置类使用的一种注解,标注它也是一个IoC容器的配置类,在这个配置类中任何标注了@Bean的方法,它的返回值都会作为Bean定义注册到Spring的IoC容器,方法名默认为这个Bean的id ,实现配置文件的功能。
@ComponentScan:相当于xml配置文件中的context:component-scan主要作用是扫描指定路径下的标识了需要装配的类, 自动装配到Spring的IoC容器中, 包括: @Component, @Repository, @Service, @Controller.
@EnableAutoConfiguration:主要作用就是帮助springboot应用把所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器中.
包含@Import注解: 这个注解就是把多个分来的容器配合合并在一个配置中.
AutoConfigurationImportSelector:根据上下文激活不同类型的Bean
@Import注解可以配合三种不同的class: 1.基于普通bean或者带有@Configuration的bean进行注入; 2.实现ImportSelector接口进行动态注入; 3.实现ImportBeanDefinitionRegistrar接口进行动态注入.
工具类SpringFactoriesLoader的作用是从classpath/META-INF/spring.factories文件中根据key加载对应的类到spring IoC容器中.
条件过滤@Conditional: 扫描spring-autoconfiguration-metadata.properties文件, 最后在扫描spring.facotories对应的类时, 会结合元数据进行过滤,通过条件过滤可以有效地减少@Configuraiton类的数量从而降低SpringBoot的启动时间.如@ConditionalOnBean/OnMissingBean/OnClass/OnResource/OnProperty
47.微服务框架:SpringCloud:
微服务是一种架构模式或者说是一种架构风格, 他提倡将单一应用程序划分成一组小的服务: 服务之间采用轻量级的通信机制互相沟通, 通常是基于HTTP的Restful API, 能够被独立部署到生产环境.
微服务的优点:
1.每个服务足够内聚, 足够小, 代码容易理解这样能聚焦一个指定的业务功能和需求;
2.开发简单开发效率高, 一个服务专一干一件事情;
3.能够被小团队单独开发;
4.使用不同语言开发;
5.容易与第三方集成;
6.微服务只是业务逻辑的代码不会和HTML, CSS或者其他界面组件混合;
7.每个服务都有自己的存储能力, 可以有自己的数据库也可以有统一的数据库.
微服务的缺点:
1.开发人员要处理分布式系统的复杂性;
2.多服务运维难度增加;
3.系统部署依赖;
4.服务间的通讯成本;
5.系统集成测试.
48.Activity工作流:

  • 工作流就是多个参与者,按照某种预定义的规则,传递业务信息,进行审核的功能一个框架(Activiti)
  • 工作流的核心对象: processEngine,调用Service,从而操作数据库的表
  • 操作数据库23表
    RepositoryService:流程定义和部署对象
    RuntimeService:执行管理,包括流程实例和执行对象(正在执行)
    TaskService:执行任务相关的(正在执行)
    HistoryService:历史管理
    IdentityService:Activiti表的用户角色组
    流程实例和执行对象的区别
  • 流程从开始到结束的最大分支,一个流程中,流程实例只有1个
  • 执行对象,就是按照流程定义的规则执行一次的操作,一个流程中,执行对象可以有多个
    流程变量在项目中的作用
  • 1:用来传递业务参数,目的就是审核人可以通过流程变量查看申请人的一些审核信息
    2:在连线的condition中设置流程变量,用来指定应该执行的连线${message==’重要’}
    3:使用流程变量指定个人任务和组任务的办理人#{userID}
    activiti工作流中,如果一个任务完成后,存在多条连线,应该如何处理?
  • 使用流程变量
  • 当一个任务完成之后,根据这几条连线的条件和设置流程变量,例如 流 程 变 量 的 名 称 = = ’ 流 程 变 量 的 值 ’ , 符 号 是 b o o l e a n 类 型 , 判 断 走 哪 条 连 线 a c t i v i t i 工 作 流 中 , 排 他 网 关 和 并 行 网 关 都 能 执 行 什 么 功 能 排 他 网 关 : 分 支 , 通 过 连 线 的 流 程 变 量 , 判 断 执 行 哪 条 连 线 , 如 果 条 件 不 符 合 , 会 执 行 默 认 的 连 线 离 开 , 注 意 : 只 能 执 行 其 中 的 一 个 流 程 。 并 行 网 关 : 可 以 同 时 执 行 多 个 流 程 , 直 到 总 流 程 的 结 束 。 可 以 对 流 程 进 行 分 支 和 聚 合 , 注 意 : 流 程 实 例 和 执 行 对 象 是 不 一 样 的 分 配 个 人 任 务 的 三 种 方 式 ∗ 直 接 给 值 , 在 X x x x . b p m n 文 件 中 指 定 ∗ 流 程 变 量 {流程变量的名称==’流程变量的值’},{}符号是boolean类型,判断走哪条连线 activiti工作流中,排他网关和并行网关都能执行什么功能 排他网关:分支,通过连线的流程变量,判断执行哪条连线,如果条件不符合,会执行默认的连线离开,注意:只能执行其中的一个流程。 并行网关:可以同时执行多个流程,直到总流程的结束。可以对流程进行分支和聚合,注意:流程实例和执行对象是不一样的 分配个人任务的三种方式 *直接给值,在Xxxx.bpmn文件中指定 *流程变量 ==boolean线activiti线线线Xxxx.bpmn{流程变量的名称}或者#{}
    *使用类 监听这个类(实现一个接口),指定任务的办理人(setAssgnee())
    个人任务和组任务的查询一样吗?
  • 不一样
  • 都是用TaskService完成(TaskService.createTasQuery)
  • 个人任务(taskAssgnee),组任务(taskCandidateUser)
  • 数据库存放,个人任务(类型:参与),组任务(类型,参与,候选)
    49.SpringBoot:

你可能感兴趣的:(java面试题,java)