发表于: 2017-12-03 23:21:52

1 830


今天完成对任务一的深度思考:
1.maven是什么,和Ant有什么区别?
Maven 和 Ant 有什么不同呢?在回答这个问题以前,首先要强调一点:Maven 和 Ant 针对构建问题的两个不同方面。Ant 为 Java 技术开发项目提供跨平台构建任务。Maven 本身描述项目的高级方面,它从 Ant 借用了绝大多数构建任务。因此,由于 Maven 和 Ant代表两个差异很大的工具,所以接下来只说明这两个工具的等同组件之间的区别,如下表所示: 
  
Maven
Ant
标准构建文件
project.xml 和 maven.xml
  
build.xml
特性处理顺序
${maven.home}/bin/driver.properties
${project.home}/project.properties
${project.home}/build.properties
${user.home}/build.properties
通过 -D 命令行选项定义的系统特性
最后一个定义起决定作用。
通过 -D 命令行选项定义的系统特性
由 任务装入的特性
第一个定义最先被处理。
构建规则
构建规则更为动态(类似于编程语言);它们是基于 Jelly 的可执行 XML。
构建规则或多或少是静态的,除非使用<script>任务
扩展语言
  
插件是用 Jelly(XML)编写的。
插件是用 Java 语言编写的。
构建规则可扩展性
通过定义 <preGoal> 和 <postGoal> 使构建 goal 可扩展。
构建规则不易扩展;可通过使用 <script> 任务模拟 <preGoal> 和 <postGoal> 所起的作用。
Maven是一个项目管理工具,它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后Maven可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。
Maven 有一个生命周期,当你运行 mvn install 的时候被调用。这条命令告诉 Maven 执行一系列的有序的步骤,直到到达你指定的生命周期。遍历生命周期旅途中的一个影响就是,Maven 运行了许多默认的插件目标,这些目标完成了像编译和创建一个 JAR 文件这样的工作。
此外,Maven能够很方便的帮你管理项目报告,生成站点,管理JAR文件,等等。
2.clean,install,package,deploy分别代表什么含义?
1、maven package:
打包到本项目,一般是在项目target目录下。
如果a项目依赖于b项目,打包b项目时,只会打包到b项目下target下,编译a项目时就会报错,因为找不到所依赖的b项目,说明a项目在本地仓库是没有找到它所依赖的b项目。
2、maven install:
打包会安装到本地的maven仓库中,如果没有设置过maven本地仓库,一般在用户/.m2目录下。
如果a项目依赖于b项目,那么install b项目时,会在本地仓库同时生成pom文件和jar文件,
总结: 
A、maven package:打包(jar等)到本项目的target下。 
B、maven install:把target下打的包(jar等)安装到本地仓库,可以供其他项目使用。
3、maven deploy:
将打包的文件发布到远程参考,提供其他人员进行下载依赖。
3.怎么样能让Maven跳过JUnit?
maven 在编译的时候跳过 test junit的写法  
把下面这个写到 pom.xml 的<pluigins>里面
<plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-surefire-plugin</artifactId>
       <configuration>
         <skip>true</skip>
       </configuration>

 </plugin>


4.为什么要用Log4j来替代System.out.println?
1.  Log4j就是帮助开发人员进行日志输出管理的API类库。它最重要的特点就可以配置文件灵活的设置日志信息的优先级、日志信息的输出目的地以及日志信息的输出格式。
2.  Log4j除了可以记录程序运行日志信息外还有一重要的功能就是用来显示调试信息。
3.  程序员经常会遇到脱离java ide环境调试程序的情况,这时大多数人会选择使用System.out.println语句输出某个变量值的方法进行调试。这样会带来一个非常麻烦的问题:一旦哪天程序员决定不要显示这些System.out.println的东西了就只能一行行的把这些垃圾语句注释掉。若哪天又需调试变量值,则只能再一行行去掉这些注释恢复System.out.println语句。

使用log4j可以很好的处理类似情况。


5.为什么DB的设计中要使用Long来替换掉Date类型?
1. 因为DATE有固定的格式,不同的地区有不同的时间表示方法,而且外国有夏令时与冬令时之分,非常麻烦
2. 其实使用BigInt也能较为清晰的表示时间
3. 大多数时候我们并不关心某一个时间点,而是发生一个动作后,需要的时间,BigInt非常方便做减法而不用转化


6.自增ID有什么坏处?什么样的场景下不使用自增ID?

好处:在添加一行时无需对自增id列赋值,在添加一行数据时可留空,会自动根据前一字段id值+1填充,单个表中能够唯一标识该字段,保证唯一性。在单个表中使用自增ID能够保证主键不重复
坏处:不存在连续性,也就是说若表中存有3行数据,ID字段为1,2,3 那么当删除字段2时就变为1,3,不具有连续性
合并表会出现ID重复的情况,上面说个使用自增ID能够在单个表中保证ID字段唯一,但两个表何为1个表,时不具有这种性质的。


7.什么是DB的索引,多大的数据量下建索引会有性能的差别,什么样的情况下该对字段建索引?

1.在经常需要搜索的列上,可以加快搜索的速度;
2.在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
3.在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;在经常需要根据范围进行搜索的列上创建索引,
4.因为索引已经排序,其指定的范围是连续的;
5.在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
6.在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。


8.唯一索引和普通索引的区别是什么,什么时候需要建唯一索引。

MySQL提供多种索引类型供选择:普通索引 、唯一性索引、主键、全文索引、单列索引与多列索引。
普通索引:
普通索引的唯一任务是加快对数据的访问速度。因此,应该只为那些最经常出现在查询条件(WHERE column=)或排序条件(ORDERBY column)中的数据列创建索引。
唯一性索引:
如果确定某个数据列只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引,MySQL会在有新记录插入数据表时,自动检查新记录的这个字段的值是否已经在某个记录的这个字段里出现过了;如果是,MySQL将拒绝插入那条新记录。也就是说,唯一索引可以保证数据记录的唯一性。事实上,在许多场合,人们创建唯一索引的目的往往不是为了提高访问速度,而只是为了避免数据出现重复。
主键:
必须为主键字段创建一个索引,这个MySQL索引就是所谓的“主索引”。主索引与唯一索引的唯一区别是:前者在定义时使用的关键字是PRIMARY而不是UNIQUE。


9.如果对学员QQ号做了一个唯一索引,在插入数据的时候,是否需要先判断这个QQ号已经存在了?

不需要.


10.CreateAt和UpdateAt的意义分别是创建时间和修改时间,这两个时间应该在什么情况下赋值?是否应该开放给外部调用的接口?

CreateAt:创建时间
UpdateAt:更新时间
CreateBy:创建人
UpdateBy:更新人
CreateAt:bigint
UpdateAt:bigint
CreateBy:Varchar
UpdateBy:Varchar
1,CreateAt/CreateBy是在数据新建时获取的,以后这个字段不会再变化。
     UpdateAt/UpdateBy是在数据进行修改操作时获取的,随着每一次的修改而做出相应的变化。
2,如果是查询接口调用,是可以的。
     如果是修改或者删除等其他接口,是不可以开放的。这两个字段涉及到对数据库操作的记录,只能由代码来自动控制,而不能把权限放开。


11.修真类型应该是直接存储Varchar,还是应该存储int?

VarChar、int是什么
1、int表示“基本整型”。 在内存中占4个字节,包含 -2^31 (-2,147,483,648) 到 2^31 - 1(2,147,483,647) 的整型数据
2、对英文(ASCII)字符占用1个字节,对一个汉字占用2个字节,CHAR存储定长数据很方便,CHAR字段上的索引效率极高,比如定义char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间
3、如果一个字段可能的值是不固定长度的,我们只知道它不可能超过10个字符,把它定义为 VARCHAR(10)是最合算的。VARCHAR类型的实际长度是它的值的实际长度+1
从字段类型的执行效率上,int最高,varchar最低。
int类型更容易建立索引和进行检索,毕竟数字类型是数据库检索的基础,char类型的毕竟需要经过转换,而varchar就更复杂了,其排序不仅需要转换和计算,还需要访问和遵循数据库的排序规则(实际上char也需要排序规则),而消耗的资源也更大。
解决方案
将五种修真类型和数字一一对应
1——散修弟子
2——内门弟子
3——首席弟子
4——真传弟子
5——修真长老


12.varchar类型的长度怎么确定?有什么样的原则,和Text和LongText的区别是什么?

字节的定义:字节(byte)是一种计量单位,8个二进制位为一个字节.表示数据量多少,它是计算机信息技术用于计量存储容量的一种计量单位。
字符的定义:字符是指计算机中使用的文字和符号,如:1、2、3、A、B、C、!、#、¥、.....、+、——等这些符号。
在UTF8编码中,一个英文字符占用一个字节,一个中文字符占用三个字节。
VARCHAR是可以保存长度可变的字符串。如:一个用户名字段不能确定长度,只知道不超过10个字符,就可以选择varchar类型。而另一种CHAR类型是只能保存长度固定的字符。如:六位的邮编、股票代码。
需要注意的是:
mysql数据库的varcahr类型在4.1以下版本中最大长度限制为255字节
mysql5.0以上的版本中varchar数据类型的长度支持到了65535字节。
Text和LongText 也是长度可变的类型
Text的最大长度是可以存储 65535 (2^16 – 1) 个字符
LongText的最大长度是可以存储4294967295 (2^32 – 1) 个字符。


13.怎么进行分页数据的查询,如何判断是否有下一页?

1.先通过SQL语句“select  count(*) from  表名 ” 查询表中的数据总条数z
2.假设每页显示m条数据,那么计算总页数p如下:z/m=y....n(n为余数),
     如果余数n!=0时,总页数p=y+1,如果余数n=0时,总页数p=y
3.在前台获取每一页数据时,控制台会去数据库离获取当页数据。
     这时使用的SQL语句是“select * from apple limit  a,b“查询第a条到第b条数据
4.判断下一页的步骤也省略了,在前面就直接算出来了总页数,我们是知道最后一页是哪一页。
14.为什么不可以用Select * from table?
select * 会降低查询效率?
答案是 YES。
SELECT 列名称 FROM 表名称
-- 检索单个列
SELECT name FROM products;
-- 检索多个列
SELECT id, name, price FROM products;
-- 检索所有的列
SELECT * FROM products;
-- 检索不同的值

SELECT DISTINCT vend_id FROM products;


15.什么是贫血模型,什么是充血模型?为什么我们会强制要求使用贫血模型?

领域模型是领域内的概念类或现实世界中对象的可视化表示,又称为概念模型或分析对象模型,它专注于分析问题领域本身,发掘重要的业务领域概念,并建立业务领域概念之间的关系。贫血模型是指使用的领域对象中只有setter和getter方法(POJO),所有的业务逻辑都不包含在领域对象中而是放在业务逻辑层。有人将我们这里说的贫血模型进一步划分成失血模型(领域对象完全没有业务逻辑)和贫血模型(领域对象有少量的业务逻辑),我们这里就不对此加以区分了。充血模型将大多数业务逻辑和持久化放在领域对象中,业务逻辑(业务门面)只是完成对业务逻辑的封装、事务和权限等的处理。下面两张图分别展示了贫血模型和充血模型的分层架构。更加细粒度的有失血模型,贫血模型,充血模型,胀血模型。贫血模型就是domain ojbect包含了不依赖于持久化的领域逻辑,而那些依赖持久化的领域逻辑被分离到Service层。失血模型简单来说,就是domain object只有属性的getter/setter方法的纯数据类,所有的业务逻辑完全由business object来完成(又称Transaction Script),这种模型下的domain object被Martin Fowler称之为“贫血的domain object”。充血模型和第二种模型差不多,所不同的就是如何划分业务逻辑,即认为,绝大多业务逻辑都应该被放在domain object里面(包括持久化逻辑),而Service层应该是很薄的一层,仅仅封装事务和少量逻辑,不和DAO层打交道。


16.Spring中的IOC是什么意思,为什么要用IOC而不是New来创建实例?
平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法。
这种开发存在的问题是 new 的类实例不便于统一管理,spring 提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。
依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。
spring 配置文件是什么?
Spring 配置文件是个XML 文件,这个文件包含了类信息,描述了如何配置它们,以及如何相互调用
什么是依赖注入?
依赖注入,是IOC的一个方面,是个通常的概念,它有多种解释。这概念是说你不用创建对象,而只需要描述它如何被创建。
你不在代码里直接组装你的组件和服务,但是要在配置文件里描述哪些组件需要哪些服务,之后一个容器(IOC容器)负责把他们组装起来。
什么是bean装配?
装配,或bean 装配是指在Spring 容器中把bean组装到一起,前提是容器需要知道bean的依赖关系,如何通过依赖注入来把它们装配到一起。
什么是自动装配?
Spring 容器能够自动装配相互合作的bean,这意味着容器不需要 constructor-arg 和 property 配置,能通过Bean工厂自动处理bean之间的协作


17.为什么要使用Interface,而不是直接使用一个实体类来完成任务?Interface和Impl这种方式的好处是什么?

接口泛指实体把自己提供给外界的一种抽象化物(可以为另一实体),用以由内部操作分离出外部沟通方法,使其能被修改内部而不影响外界其他实体与其交互的方式。
[访问修饰符] interface [接口名] {
[定义常量]
[定义抽象方法]
}
访问修饰符默认为public
什么是多重继承
指的是一个类可以同时继承多个父类的行为和特征功能
为什么要摒弃多重继承用接口
如果B,C都继承与D且都改写了D里的同一个方法,如 void a()变成void b()和 void c()。如果让A同时继承B和C,该用b的方法还是c就冲突了。
同时对于接口来说只规定了a方法没有实现因此就不会出现a()的两种实现,因此接口的继承也就没有在上面说的这个问题了
为什么要使用接口?而不是直接实现呢
JAVA只允许一个类只能继承一个抽象类,而一个类却可以继承实现多个接口。
接口与实现不分离,则只能继承一个抽象类,但有时候需要继承多个


18.为什么要处理异常,Try/Catch应该在什么样的场景下使用,在真实的系统中,会出现网络中断,

DB连接不上的错误吗?多久会发 生一次?
可能每一只程序猿都有这样一个梦想
程序永远不会出现问题,用户输入的数据永远是正确的,逻辑一定没有任何问题 ,选择打开的资源也一定是存在的,连接永远是OK的,内存永远是够用的……
简单来说就是:0 error(s), 0 warning(s)
但是,不存在的...
一场总是不期而至,所以我们要处理异常
异常处理机制:天有不测风云,人有旦夕祸福,Java的程序代码也如此,JAVA远在设计之初就考虑到了这个问题,于是就设计了JAVA的异常处理机制。而发展至今的异常处理机制现在也已经非常的完善。
什么是异常处理?
如果某个方法不能按照正常的途径完成任务,
就可以通过另一种路径退出方法。
在这种情况下会抛出一个封装了错误信息的对象。
此时,这个方法会立刻退出同时不返回任何值。
另外,调用这个方法的其他代码也无法继续执行,
异常处理机制会将代码执行交给异常处理器。
异常的分类
java中的异常机制包括Error和Exception两个部分。他们都继承自一个共同的基类Throwable
Error属于JVM运行中发生的一些错误,虽然并不属于开发人员的范畴,但是有些Error还是由代码引起的,比如StackOverflowError经常由递归操作引起
Exception分为两种,检查类型(checked)和未检查类型(unchecked)。检查类型的异常就是说要程序员明确的去声明或者用try..catch语句来处理的异常,而非检查类型的异常则没有这些限制
下面看一张树状图
换一种说法
对于严重的,java通过Error类来描述
对于Error一般不编写针对性的代码对其进行处理
对于非严重的,java通过Exception类来描述
对于Exception可以使用针对性的处理方式进行处理
Java异常处理涉及到五个关键字
分别是:try、catch、finally、throw与throws,每个关键字不能被单独使用
1.try:它里面放置可能引发异常的代码
2.catch:后面对应异常类型和一个代码块,用于表明该catch块用于处理这种类型的代码块,可以有多个catch块。
3.finally:主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件),异常机制总是保证finally块总是被执行。
4.throw:用于抛出一个实际的异常,可以单独作为语句使用,抛出一个具体的异常对象。
5.throws:用在方法签名中,用于声明该方法可能抛出的异常。
注意点1:只有try块是必须的,也就是说如果没有try块,则不可能有后面的catch块和finally块;
注意点2:catch块和finally块都是可选的,但catch块和finally块至少出现其中之一,也可以同时出现;
注意点3:可以有多个catch块,捕获父类异常的catch块必须位于捕获子类异常的后面;
注意点4:不能只有try块,既没有catch块,也没有finally块;
注意点5:多个catch块必须位于try块之后,finally块必须位于所有catch块之后。
一般情况下,不要再finally块中使用renturn或throw等导致方法终止的语句,因为一旦使用,将会导致try块、catch块中的return、throw语句失效。
在try块中使用退出虚拟机的语句,不过这会导致整个程序终止,最好还是不要在finally中写return和throw语句


19.日志应该怎么打,在什么位置,需要打印出来什么样的关键参数?

记录日志的方式有多个,这几种我们也都见到过:
① 最简单的方式:System.out.println("徐小明");
②Java.util.logging.logger
在JDK1.4版本之后,提供了日志的API,可以往文件中写日志了。
public class TestLogJava {
         public static void main (String[] args) throws IOException {
         Logger log = Logger.getLogger("testlog");
        log.setLevel(Level.ALL);
        FileHandler fileHandler =new FileHandler("testlog.log");
        fileHandler.setLevel(Level.ALL);
        fileHandler.setFormatter(new LogFormatter());
        log.addHandler(fileHandler);
        log.info("This is test java util log");
   }
}
这是在网上找到的一个例子,可以看到首先是定义了一个Logger的实例,并设置了log的级别,接着添加了一个fileHander就是把日志写入文件中。在写入文件的时候,定义一个LogFormatter队日志进行格式的渲染。
③Log4j
log4j是Apache提供的记录日志的jar包。
在使用时,首先要导入log4j的jar包,然后要配置log4j.properties。
配置实例:
log4j.rootLogger=DEBUG,Console,Stdout
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.appender.Console.File=D:\\Tomcat 5.5\\logs\\qc.log
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
log4j.appender.Stdout = org.apache.log4j.DailyRollingFileAppender
log4j.appender.Stdout.Append = true
log4j.appender.Stdout.Threshold = DEBUG
log4j.appender.Stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.Stdout.layout.ConversionPattern =%-d{yyyy-MM-dd HH/:mm/:ss}  [ %t/:%r ] - [ %p ]  %m%n
log4j日志一共有五种级别:DEBUG、INFO、WARN、ERROR、FATAL。
--log4j.rootLogger=DEBUG,Console,Stdout
这里指定了日志级别为debug,并将等级为debug的日志信息输出到Console和Stdout两个目的地。Console和Stdout名字可以随意起,只要在后面定义了就行。
--log4j.appender.Console=org.apache.log4j.ConsoleAppender
此句为定义名为Console的输出端是哪种类型,可以是:
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
--log4j.appender.Console.layout=org.apache.log4j.PatternLayout
此句为定义名为Console的输出端的layout是哪种类型,可以是
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
--log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern,打印参数如下:
%m 输出代码中指定的消息
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名
%n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。
[QC]是log信息的开头,可以为任意字符,一般为项目简称。
--log4j.appender.Console.File=D:\\Tomcat 5.5\\logs\\qc.log
此句为定义名为Console的输出端的文件名为D:\\Tomcat 5.5\\logs\\qc.log可以自行修改。
④Commons-logging
Commons-logging也是Apache提供的日志jar包。
Commons-logging提供的是一个日志(Log)接口(Interface),是为那些需要建立在不同环境下使用不同日志架构的组件或库的开发者创建的其中包括Apache Log4j以及Java log的日志架构。把日志信息抽象成commons-logging的Log接口,并由commons-logging在运行时决定使用哪种日志架构。因为Log4j的强大功能,commons-logging一般会和Log4j一起使用,这几乎成为了Java日志的标准工具。


20.为什么需要单步调试?Debug的时候IDE是怎么找到源码的?

单步调试可以看到代码每一步执行的过程,其中包含了我们看不到后台调用.


21.可否远程连接到线上直接调试?真实的项目中,遇到问题的排查方案是什么?

我们一般在本地写代码时,如果程序出现问题了,一般情况下,我们会在程序中打各种log,调试,找出问题,修改,测试,部署到服务器,再测试。但如果在真实项目中的呢,这样做虽然也可以,显然是不方便的。
真实项目中,我们可以通过远程连接的方式,进行调试
远程调试:服务端程序运行在一台远程服务器上,我们可以在本地服务端的代码(前提是本地的代码必须和远程服务器运行的代码一致)中设置断点,每当有请求到远程服务器时时能够在本地知道远程服务端的此时的内部状态。
1.远程调试适用于哪个阶段?开发?测试?线上?

(个人认为)适用于测试阶段,在线上肯定是不行的。很多人访问,都不知道调试的是哪个。开发阶段的话,一般是分功能模块的,每个人负责自己的模块,分开开发测试。远程调试,一般在于开发完成后的集中测试(功能衔接),这时项目已经部署到测试服务器上了。


明天计划的事情:

继续Spring MVC的学习
遇到的问题:null


收获:

对任务一又一次进行了回顾



返回列表 返回列表
评论

    分享到