前段时间浏览java吧,遇到一个新人面试,坐标上海,面试了四五家的面试题贴在贴吧里,但是没有给出答案,很是无语,于是自己总结了一份记录在这里,以便需要的人查看。
第一题:Spring是什么
答:Spring是一个开源的轻量级Java SE(Java 标准版本)/Java EE(Java 企业版本)开发应用框架,其目的是用于简化企业级应用程序开发。Spring框架除了帮我们管理对象及其依赖关系,还提供像通用日志记录、性能统计、安全控制、异常处理等面向切面的能力,还能帮我管理最头疼的数据库事务,本身提供了一套简单的JDBC访问实现,提供与第三方数据访问框架集成(如Hibernate、JPA),与各种Java EE技术整合(如Java Mail、任务调度等等),提供一套自己的web层框架Spring MVC、而且还能非常简单的与第三方web框架集成
Spring能帮我们做什么?Spring除了不能帮我们写业务逻辑,其余的几乎什么都能帮助我们简化开发!
http://blog.csdn.net/lp1052843207/article/details/51253071
第二题:什么是IOC
答:IOC就是依赖、依赖倒置、依赖注入、控制反转
依赖:就是有联系,有地方使用到它就是有依赖它,一个系统不可能完全避免依赖。如果你的一个类或者模块在项目中没有用到它,恭喜你,可以从项目中剔除它或者排除它了,因为没有一个地方会依赖它。两个类之间的调用就是一种依赖
依赖倒置:就是通过增加接口来降低耦合度,进行优化,因为接口是稳定的
依赖反转:就是讲控制层的控制权交给配置文件,而不是代码,我们只需要修改配置文件就可以控制功能
依赖注入:就是由IoC容器在运行期间,动态地将某种依赖关系注入到对象之中。
1、基于代理的AOP
2、纯简单java对象切面
3、@Aspect注解形式的
4、注入形式的Aspcet切面
我认为的主要思想就是找到切点,切面,实现aop 我接触的一般都是在配置文件中通过全局匹配定义切点,然后通过id 增强切面。- <!-- 创建一个增强 advice -->
- <bean id ="sleepHelper" class="com.tgb.springaop.aspect.SleepHelper"/>
- <bean id="lina" class="com.tgb.springaop.service.impl.ChenLliNa"/>
- <!-- 定义切点 匹配所有的sleep方法-->
- <bean id ="sleepPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
- <property name="pattern" value=".*sleep"></property>
- </bean>
- <!-- 切面 增强+切点结合 -->
- <bean id="sleepHelperAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
- <property name="advice" ref="sleepHelper"/>
- <property name="pointcut" ref="sleepPointcut"/>
- </bean>
- <!-- 定义代理对象 -->
- <bean id="linaProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="target" ref="lina"/>
- <property name="interceptorNames" value="sleepHelperAdvisor"/>
- <!-- <property name="proxyInterfaces" value="com.tgb.springaop.service.Sleepable"/> -->
- </bean>
1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id".
2. $将传入的数据直接显示生成在sql中。如:order by $user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id.
3. #方式能够很大程度防止sql注入。
4.$方式无法防止Sql注入。
5.$方式一般用于传入数据库对象,例如传入表名.
6.一般能用#的就别用$.
MyBatis排序时使用order by 动态参数时需要注意,用$而不是#
字符串替换
这里MyBatis不会修改或转义字符串。
重要:接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。
第五题:什么是redis,它能做什么
答:Redis简单来说就是一个key-value存储系统,通过键值对将数据存储到内存中,注意这里是内存,而不是数据库,所以存储效率非常高,缺点就是占用内存很大,比如网站首页一天有100万人访问,其中有一个板块为推荐新闻。要是直接从数据库查询,那么一天就要多消耗100万次数据库请求。上面已经说过,Redis支持丰富的数据类型,所以这完全可以用Redis来完成,将这种热点数据存到Redis(内存)中,要用的时候,直接从内存取,极大的提高了速度和节约了服务器的开销。
使用方法:在服务器下载安装好redis,然后通过代码写入读取方式就可以直接使用,是在服务器上安装使用,而不是在客户端做操作,存取代码的逻辑后台实现,只是存取的位置不是在数据库而是在内存!,,这是思想误区,便于理解。
第六题:用Quartz处理定时任务
答:比如每天凌晨恢复疲劳值,这就是一种定时任务
第一步:引包,下面是必要的四个包
1、log4j-1.2.16
2、quartz-2.1.7
3、slf4j-api-1.6.1.jar
4、slf4j-log4j12-1.6.1.jar
第二步:创建要被执行的任务类,实现org.quartz.job接口的类并实现相应方法第三步:创建任务调度,并执行,直接上代码
- public class Test {
- public void go() throws Exception {
- // 首先,必需要取得一个Scheduler的引用
- SchedulerFactory sf = new StdSchedulerFactory();
- Scheduler sched = sf.getScheduler();
- //jobs可以在scheduled的sched.start()方法前被调用
- //job 1将每隔20秒执行一次
- JobDetail job = newJob(myJob.class).withIdentity("job1", "group1").build();
- CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1").withSchedule(cronSchedule("0/20 * * * * ?")).build();
- Date ft = sched.scheduleJob(job, trigger);
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
- System.out.println(job.getKey() + " 已被安排执行于: " + sdf.format(ft) + ",并且以如下重复规则重复执行: " + trigger.getCronExpression());
- // job 2将每2分钟执行一次(在该分钟的第15秒)
- job = newJob(myJob.class).withIdentity("job2", "group1").build();
- trigger = newTrigger().withIdentity("trigger2", "group1").withSchedule(cronSchedule("15 0/2 * * * ?")).build();
- ft = sched.scheduleJob(job, trigger);
- System.out.println(job.getKey() + " 已被安排执行于: " + sdf.format(ft) + ",并且以如下重复规则重复执行: "+ trigger.getCronExpression());
- // 开始执行,start()方法被调用后,计时器就开始工作,计时调度中允许放入N个Job
- sched.start();
- try {
- //主线程等待一分钟
- Thread.sleep(60L * 1000L);
- } catch (Exception e) {}
- //关闭定时调度,定时器不再工作
- sched.shutdown(true);
- }
- public static void main(String[] args) throws Exception {
- Test test = new Test();
- test.go();
- }
- }
OK了,Job1和Job2就会被安排为定时执行了。此时程序是可以执行的了,但是可能会输出WARN级别日志,这是因为没有加log4j的配置文件,加上配置文件,就OK了。这里需要说明的地方只有一个,其它的可以直接Copy到您的项目里面。看代码:
- CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1").withSchedule(cronSchedule("0/20 * * * * ?")).build();
CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1").withSchedule(cronSchedule("0/20 * * * * ?")).build();
"0/20 * * * * ?"代表什么?这是关键,搞明白这个,Quartz就能帮助你解决大部分的定时执行任务的功能。详细解释请看下面转载见容
常用示例:
0 0 12 * * ? | 每天12点触发 |
0 15 10 ? * * | 每天10点15分触发 |
0 15 10 * * ? | 每天10点15分触发 |
0 15 10 * * ? * | 每天10点15分触发 |
0 15 10 * * ? 2005 | 2005年每天10点15分触发 |
0 * 14 * * ? | 每天下午的 2点到2点59分每分触发 |
0 0/5 14 * * ? | 每天下午的 2点到2点59分(整点开始,每隔5分触发) |
0 0/5 14,18 * * ? | 每天下午的 2点到2点59分(整点开始,每隔5分触发) 每天下午的 18点到18点59分(整点开始,每隔5分触发) |
0 0-5 14 * * ? | 每天下午的 2点到2点05分每分触发 |
0 10,44 14 ? 3 WED | 3月分每周三下午的 2点10分和2点44分触发 |
0 15 10 ? * MON-FRI | 从周一到周五每天上午的10点15分触发 |
0 15 10 15 * ? | 每月15号上午10点15分触发 |
0 15 10 L * ? | 每月最后一天的10点15分触发 |
0 15 10 ? * 6L | 每月最后一周的星期五的10点15分触发 |
0 15 10 ? * 6L 2002-2005 | 从2002年到2005年每月最后一周的星期五的10点15分触发 |
0 15 10 ? * 6#3 | 每月的第三周的星期五开始触发 |
0 0 12 1/5 * ? | 每月的第一个中午开始每隔5天触发一次 |
0 11 11 11 11 ? | 每年的11月11号 11点11分触发(光棍节) |