解决POST、GET请求中文乱码问题
- 解决post请求乱码问题: 在web.xml中配置一个CharacterEncodingFilter过滤器,设置成 utf-8;
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
@RequestMapping(value = "/add", produces = "text/plain;charset=utf-8")
get 请求中文参数出现乱码解决方法有两个
- 修改 tomcat 配置文件添加编码与工程编码一致,如下:
<ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/
- 另外一种方法对参数进行重新编码
//ISO8859-1 是 tomcat 默认编码,需要将 tomcat 编码后的内容按 utf-8 编码 String userName = new String(request.getParamter(“userName”).getBytes(“ISO8859-1”),“utf-8”)
Redis
Redis作用
- 内存存储、持久化,放在内存中,断电即失(持久化重要(RDB、AOF))
- 效率高,可以用于告诉缓存
- 发布订阅系统
- 地图信息分析
- 计数器、计数器(浏览量)
特性
- 多样的数据类型
- 持久化
- 集群
- 事务
基础知识
- redis默认
16
个数据库,默认使用第0个,可以使用select进行切换数据库 常用命令
#查看数据库大小 DBSIZE #查看所有的key KEY * #清空当前数据库 flushdb #清空所有数据库 flushall
Redis是单线程的
Redis是基于内存操作,所以他的瓶颈在于机器的内存和网络带宽
SpringBean的配置详解
Bean的实例化配置
- 静态工厂方法实例化Bean
- 实例工厂方法实例化Bean
- 实现FactoryBean规范延迟实例化Bean
Bean的依赖注入配置
依赖注入的两种方式
通过Bean的set方法注入
通过构造Bean的方法注入
ref用于引用其他的Bean的id;value用于注入普通属性值.
依赖注入的数据类型有如下三种:
- 普通数据类型,例如:String,int,boolean等,通过value属性指定
- 引用数据类型,例如:UserDaoImpl,DataSource等,通过ref属性指定
- 集合数据类型,例如:List,Map,Properties等
Spring 声明式事务无效可能的原因有哪些?
答:可能的原因如下:
- MySQL 使用的是 MyISAM 引擎,而 MyISAM 是不支持事务的;
- @Transactional 使用在非
public
方法上,@Transactional 注解只能支持public
级别,其他类型声明的事务不会生效; - @Transactional 在同一个类中无事务方法 A() 内部调用有事务方法 B(),那么此时 B() 事物不会生效。Spring 中的 AOP 的底层实现原理是什么?
答:Spring AOP 的底层实现原理就是动态代理。Spring AOP 的动态代理有两种实现方式,对于接口使用的是 JDK 自带的动态代理来实现的,而对比非接口使用的是 CGLib 来实现的。
Spring 中 Bean 的生命周期
答:Spring 中 Bean 的生命周期如下:
- ① 实例化 Bean:对于 BeanFactory 容器,当客户向容器请求一个尚未初始化的 Bean 时,或初始化 Bean 的时候需要注入另一个尚未初始化的依赖时,容器就会调用 createBean 进行实例化。对于 ApplicationContext 容器,当容器启动结束后,通过获取 BeanDefinition 对象中的信息,实例化所有的 Bean;
- ② 设置对象属性(依赖注入):实例化后的对象被封装在 BeanWrapper 对象中,紧接着 Spring 根据 BeanDefinition 中的信息以及通过 BeanWrapper 提供的设置属性的接口完成依赖注入;
- ③ 处理 Aware 接口:Spring 会检测该对象是否实现了 xxxAware 接口,并将相关的 xxxAware 实例注入给 Bean:
- 如果这个 Bean 已经实现了 BeanNameAware 接口,会调用它实现的 setBeanName(String BeanId) 方法,此处传递的就是 Spring 配置文件中 Bean 的 id 值;
- 如果这个 Bean 已经实现了 BeanFactoryAware 接口,会调用它实现的 setBeanFactory() 方法,传递的是 Spring 工厂自身;
- 如果这个 Bean 已经实现了 ApplicationContextAware 接口,会调用 setApplicationContext(ApplicationContext) 方法,传入 Spring 上下文;
- ④ BeanPostProcessor:如果想对 Bean 进行一些自定义的处理,那么可以让 Bean 实现了 BeanPostProcessor 接口,那将会调用 postProcessBeforeInitialization(Object obj, String s) 方法;
- ⑤ InitializingBean 与 init-method:如果 Bean 在 Spring 配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法;
- ⑥ 如果这个 Bean 实现了 BeanPostProcessor 接口,将会调用 postProcessAfterInitialization(Object obj, String s) 方法;由于这个方法是在 Bean 初始化结束时调用的,因而可以被应用于内存或缓存技术;
以上几个步骤完成后,Bean 就已经被正确创建了,之后就可以使用这个 Bean 了。
- ⑦ DisposableBean:当 Bean 不再需要时,会经过清理阶段,如果 Bean 实现了 DisposableBean 这个接口,会调用其实现的 destroy() 方法;
- ⑧ destroy-method:最后,如果这个 Bean 的 Spring 配置中配置了 destroy-method 属性,会自动调用其配置的销毁方法。
Spring 中都是用到的设计模式
答:Spring 中使用的设计模式如下:
- 工厂模式:通过 BeanFactory、ApplicationContext 来创建 bean 都是属于工厂模式;
- 单例、原型模式:创建 bean 对象设置作用域时,就可以声明 Singleton(单例模式)、Prototype(原型模式);
- 察者模式:Spring 可以定义一下监听,如 ApplicationListener 当某个动作触发时就会发出通知;
- 责任链模式:AOP 拦截器的执行;
- 策略模式:在创建代理类时,如果代理的是接口使用的是 JDK 自身的动态代理,如果不是接口使用的是 CGLIB 实现动态代理。
设置 Ehcache 为 MyBatis 的二级缓存
直接在 XML 中配置开启 EhcacheCache
<mapper namespace="com.interview.repository.ClassesReposirory">
<!-- 开启二级缓存 -->
<cache type="org.mybatis.caches.ehcache.EhcacheCache" >
<!-- 缓存创建以后,最后一次访问缓存的时间至失效的时间间隔 -->
<property name="timeToIdleSeconds" value="3600"/>
<!-- 缓存自创建时间起至失效的时间间隔-->
<property name="timeToLiveSeconds" value="3600"/>
<!-- 缓存回收策略,LRU 移除近期最少使用的对象 -->
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>
<select id="findById" parameterType="java.lang.Long" resultType="com.interview.entity.Classes">
select * from classes where id = #{id}
</select>
</mapper>
反射的基本使用
下来我们通过反射调用类中的某个方法,来学习反射的基本使用。
使用反射调用类中的方法,分为三种情况:
- 调用静态方法
- 调用公共方法
- 调用私有方法
假设有一个实体类 MyReflect 包含了以上三种方法,代码如下:
package com.interview.chapter4;
class MyReflect {
// 静态方法
public static void staticMd() {
System.out.println("Static Method");
}
// 公共方法
public void publicMd() {
System.out.println("Public Method");
}
// 私有方法
private void privateMd() {
System.out.println("Private Method");
}
}
下面分别来看,使用反射如何调用以上三种类型的方法。
① 反射调用静态方法
Class myClass = Class.forName("com.interview.chapter4.MyReflect");
Method method = myClass.getMethod("staticMd");
method.invoke(myClass);
② 反射调用公共方法
Class myClass = Class.forName("com.interview.chapter4.MyReflect");
// 创建实例对象(相当于 new )
Object instance = myClass.newInstance();
Method method2 = myClass.getMethod("publicMd");
method2.invoke(instance);
③ 反射调用私有方法
Class myClass = Class.forName("com.interview.chapter4.MyReflect");
// 创建实例对象(相当于 new )
Object object = myClass.newInstance();
Method method3 = myClass.getDeclaredMethod("privateMd");
method3.setAccessible(true);
method3.invoke(object);
反射使用总结
反射获取调用类可以通过 Class.forName(),反射获取类实例要通过 newInstance(),相当于 new 一个新对象,反射获取方法要通过 getMethod(),获取到类方法之后使用 invoke() 对类方法进行调用。如果是类方法为私有方法的话,则需要通过 setAccessible(true) 来修改方法的访问限制,以上的这些操作就是反射的基本使用。