很多程序员在进入正式工作之后越来越不注重基础和理论,我记得老师曾经说过:“基础好,样样通,理论强,处处用。”现在有时间了,正好整理一下理论和基础,一来自己复习,二来方便一下找工作的同仁参考。
Spring篇(基于3.X)
一般来说Spring的面试中的问题就是 AOP 和 IOC这两种,这是由于大连很多框架都是将spring用在管理代码上:
一.ioc技术:
①属性注入:
<bean id="bean名称" class="类包+类名">
<property name="属性名" value="值"></property>
</bean>
②构造函数注入:
<bean id="bean名称" class="类包+类名">
<constructor-arg type="类型" value="具体值" />
</bean>
而对于构造函数的注入:
我们可以通过配置索引的方式,消除歧义,比如:
<constructor-arg index="序号" type="类型">
<value>具体值</value>
</constructor-arg>
注意:索引是从0开始,配置之后我们的拦截器就会按照构造函数中参数的出现顺序对其赋值。
值注入陷阱:
如果:<property name="属性名"><value></value></property>
那么:请问得到的值是什么?
错误回答:null
正确回答:是"",即空字符串,为什么?因为我们的spring会将这种值默认的变成 空字符串,那么,我想要null,该如何实现?
spring给我们提供了一个<null/>标签
如何注入 set map list?
spring 可以注入 set map list 等集合:
<bean id="bean名称" class="类包+类名">
<property name="LIST集合名">
<list>
<value>值1<value>
<value>值2<value>
<value>值3<value>
</list>
</property>
<property name="SET集合名">
<set>
<value>值1<value>
<value>值2<value>
<value>值3<value>
</set>
</property>
<property name="MAP集合名">
<map>
<entery>
<key><value>键名<value></key>
<value>值名</value>
</entery>
</map>
</property>
</bean>
二.AOP技术:
基于注解的实现:
第一,我们要明确的是,我们的切点类需要在配置文件中声明一个匿名类:
第二,就是注解,而对于注解很多人容易将他们的具体实现弄混杂,我们可以通过这张表,一目了然:
类别
|
函数
|
入参
|
说明
|
方法切点函数
|
execution()
|
方法
匹配模式串
|
表示满足某一匹配模式的所有目标类方法连接点。如execution(* greetTo(..))表示所有目标类中的greetTo()方法。
|
@annotation()
|
方法注
解类名
|
表示标注了特定注解的目标方法连接点。如@annotation(com.baobaotao.anno.NeedTest)表示任何标注了@NeedTest注解的目标类方法。
| |
方法入参切点函数
|
args()
|
类名
|
通过判别目标类方法运行时入参对象的类型定义指定连接点。如args(com.baobaotao.Waiter)表示所有有且仅有一个按类型匹配于Waiter的入参的方法。
|
@args()
|
类型注
解类名
|
通过判别目标方法的运行时入参对象的类是否标注特定注解来指定连接点。如@args(com.baobaotao.Monitorable)表示任何这样的一个目标方法:它有一个入参且入参对象的类标注@Monitorable注解。
| |
目标类切点函数
|
within()
|
类名匹配串
|
表 示特定域下的所有连接点。如within(com.baobaotao.service.*)表示com.baobaotao.service包中的所有 连接点,也即包中所有类的所有方法,而within(com.baobaotao.service.*Service)表示在 com.baobaotao.service包中,所有以Service结尾的类的所有连接点。
|
target()
|
类名
|
假如目标类按类型匹配于指定类,则目标类的所有连接点匹配这个切点。如通过target(com.baobaotao.Waiter)定义的切点,Waiter、以及Waiter实现类NaiveWaiter中所有连接点都匹配该切点。
| |
@within()
|
类型注解类名
|
假如目标类按类型匹配于某个类A,且类A标注了特定注解,则目标类的所有连接点匹配这个切点。
如@within(com.baobaotao.Monitorable)定义的切点,假如Waiter类标注了@Monitorable注解,则Waiter以及Waiter实现类NaiveWaiter类的所有连接点都匹配。
| |
@target()
|
类型注解类名
|
目标类标注了特定注解,则目标类所有连接点匹配该切点。如@target(com.baobaotao.Monitorable),假如NaiveWaiter标注了@Monitorable,则NaiveWaiter所有连接点匹配切点。
| |
代理类切点函数
|
this()
|
类名
|
代理类按类型匹配于指定类,则被代理的目标类所有连接点匹配切点。这个函数比较难理解,这里暂不举例,留待后面详解。
|
这张表熟悉之后,基本上AOP技术就已经掌握了。
三.事物的配置:
第一步,我们要配置的是数据库,我们以mysql为例子,我们需要调用的类是:
org.springframework.jdbc.datasource.DriverManagerDataSource
第二步,是ibatis的配置,spring给我们提供了很好的整合类:
SqlMapClientFactoryBean
第三步,事务处理,我们用:
org.springframework.jdbc.datasource.DataSourceTransactionManager
来控制
第四步,配置AOP和事务
具体的代码可以参照下文的:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<!-- 配置资源文件 -->
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:spring/config.properties</value>
</property>
</bean>
<!-- 配置数据库 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/sa-web?useUnicode=true&characterEncoding=UTF8"></property>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!-- ibatis 配置 -->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:sqlMaps/sqlMapConfig.xml"></property>
</bean>
<bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">
<constructor-arg>
<ref bean="sqlMapClient"></ref>
</constructor-arg>
</bean>
<!-- 事务处理 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="is*" read-only="true" />
<tx:method name="add*" rollback-for="Exception" />
<tx:method name="del*" rollback-for="Exception" />
<tx:method name="update*" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<!-- 事物配置 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<aop:config>
<!--proxy-target-class="true"强制使用cg-lib-->
<aop:pointcut id="serviceMethod" expression="execution(* com.sa.web.dao.impl.*Impl.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
</aop:config>
</beans>
插入一个知识点,如何配置文档xml所在的地方呢?
两种:在web.xml中:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>配置文件位置</param-value>
</context-param>
在spring 相关的配置文件中:
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:com/roiland/spring/config.properties</value>
</property>
</bean>
四,关于SPRING MVC
很多公司不喜欢用spring mvc可能是他在前后台获取数据上真的是没有struts2来的方便,但是我们既然用过了,就要把它当成我们的相关经验
至于controller这,我没有什么好说的,我们只需要明白,第一 spring mvc 中的modelandview 这个类中,不仅可以返回一个 jsp或是html页面(要加扩展名,还可以返回一个map的形式。在jsp中可以获取到.然后是如果我们想重定向就是newRedirecty就可以了。)
我们要说的是怎么返回json?
可以参照:
http://blog.youkuaiyun.com/longxia1987/article/details/7732470 的文章,我认为在面试中答出需要用AnnotationMethodHandlerAdapter即可。
其他:
1.怎么监听request?说白了就是怎么样像struts那样获取 request呢?我们只需要给个监听:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
2.如何监听上下文?这是在整合框架中用到最多的方式:
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
3.spring的拦截器:
<!—暂时省略 -->
4.spring的rmi:
服务端:
<!--CAS功能web service服务接口-->
<beanclass="org.springframework.remoting.rmi.RmiServiceExporter">
<propertyname="serviceName" value="对外暴露的接口名" />
<propertyname="service" ref="实现类" />
<propertyname="serviceInterface" value="接口类所在" />
<propertyname="registryPort" value="注册接口" />
<propertyname="servicePort" value="通信时使用端口,可以不配" />
</bean>
客户端:
<beanid="statisticService"class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<propertyname="serviceUrl" value="rmi://我们发布的服务地址" />
<propertyname="serviceInterface" value="我们的接口,这个要和服务端的一模一样" />
<!-- 表示在启动时不检测接口连接-- >
<propertyname="lookupStubOnStartup">
<value>false</value>
</property>
<!-- 表示在连接失败时刷新-- >
<propertyname="refreshStubOnConnectFailure">
<value>true</value>
</property>
</bean>
ibatis 篇:
面试中的ibatis应该没什么难度,我们在面试的时候回答以下点,就足够了:
typeAlias:他的意思是将我们可能用到的类取个别名。
selectKey: 意思是说获取当前主键,其实这个是在执行成功后才会执行的操作,所以:我们配置<![CDATA[ SELECT 1]]>即可。
parameterClass 这是我们的传入参数。
resultClass 这是我们的返回参数。
在动态标签中的prepend 是接在 动态标签内容后面的,而property顾名思义就是我们需要判断遍历之类的操作。
所以我们继续说便利标签:
<iterateconjunction="," open="(" close=")"property="companyIds" >
此时需要注意的是标签内部要写成 #list[]#的形式。
模糊查询:CONCAT('%',#adminName#,'%')
struts2篇:
关于name和namespace的区别:name是用来满足包之间的继承的,而namespace是访问包下的action的路径,如果不配namespace的话,那么默认访问路径就是name的路径了。
拦截器的配置:明确几个参数。
interceptor-stack 这里面配置了拦截器的引用
interceptor-ref 这是引用的集体拦截器,一般来说,我们都要引用默认的拦截器,其次,我们将自定义拦截器放在默认拦截器的前面.
如何使用?在另一个包中一般拦截器所在的包可以让其他的包继承,这样使用起来比较方便。default-interceptor-ref 就是你配置的 interceptor-stack 的名字。
而global-results顾名思义就是一个全局的返回页面之类的东西,
好的,这样就OK了。在此提供一个带acftion的例子。见下文。
还要说明的是:如果你要返回json,可以继承json-default这个包,对于继承多个包直接用逗号隔开。
<package name="main" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="userInterceptor" class="com.sa.web.util.interceptoer.UserInterceptor"/>
<interceptor-stack name="sauser">
<interceptor-ref name="userInterceptor"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="sauser"/>
<global-results>
<result name="nologin">/view/behind/userlogin.jsp</result>
</global-results>
<!-- 前台主页 -->
<action name="index" class="mainAction0001" method="init">
<result name="success">/view/front/index.jsp</result>
</action>
<!-- 后台管理员登陆页 -->
<action name="adminlogin" class="adminLoginAction0001" method="init">
<result name="success">/view/behind/login.jsp</result>
</action>
<action name="userLogin" class="userAction" method="userLogin">
<result name="login">/view/front/studentInfo.jsp</result>
<result name="input">/view/behind/userlogin.jsp</result>
</action>
</package>
<package name="main-json" extends="json-default" namespace="/">
<!-- 获取问答信息 -->
<action name= "findStuDetailList" class="stuDetailAction" method="findStuDetailList">
<result name="success" type="json">
<param name="excludeProperties">stuDetailDao,stuDetail</param>
</result>
</action>
</package>
插入一个概念多线程的问题:
synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程(例如线程A),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法,有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,直接运行。它包括两种用法:synchronized 方法和 synchronized 块。
再说说 两种实现多线程的区别:
在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的。一个类只要继承了Thread类同时覆写了本类中的run()方法就可以实现多线程操作了,但是一个类只能继承一个父类,这是此方法的局限。
Start:
用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到spu时间片,就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。
Run:
run()方法只是类的一个普通方法而已,如果直接调用Run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。
总结:调用start方法方可启动线程,而run方法只是thread的一个普通方法调用,还是在主线程里执行。
先写到这了,这文章我会不定期的持续更新的。
先写到这了,不得不说面试是个好事儿,可以让你把知识重新复习一遍。但是频繁跳槽是不可取的。同仁们加油吧!