个人阶段性学习总结
实习报告总结 1.struts+spring+hibernate框架学习及使用: a.struts2主要负责接收网页中表单提交的数据,然后通过 Action 进行处理,再 Forward 到对应的网页; b.spring相当于一个大容器,将struts2和hibernate整合进来。spring负责业务层管理,主要利用IoC和A
这一个月的个人学习总结
1.struts+spring+hibernate框架学习及使用:
a.struts2主要负责接收网页中表单提交的数据,然后通过 Action 进行处理,再 Forward 到对应的网页;
b.spring相当于一个大容器,将struts2和hibernate整合进来。spring负责业务层管理,主要利用IoC和AoP对action,service,dao,数据访问源以及声明式事务等管理;
c.hibernate主要负责持久化层,完成数据库的 crud 操作。
2.struts2学习:
1.Struts2基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互,Struts2框架的绝大部分功能都是通过拦截器来完成的,
当FilterDispatch拦截到用户请求后,大量拦截器将会对用户请求进行处理,然后调用定义的Action类中的方法进行处理请求,其工作流程如下:
(1) 用户访问页面,客户端(Client)向Action发用一个请求(Request);
(2) Container通过web.xml映射请求,并获得控制器(Controller)的名字
(3) 容器(Container)调用Struts2核心过滤器(StrutsPrepareAndExecuteFilter)。在Struts2(StrutsPrepareAndExecuteFilter或FilterDispatcher)。在Struts2.1以前调用FilterDispatcher,Struts2.1以后调用StrutsPrepareAndExecuteFilter。
(4) 控制器(Controller)通过ActionMapper获得Action的信息
(5) 控制器(Controller)调用ActionProxy
(6) ActionProxy读取struts.xml文件获取action和interceptor stack的信息。
(7) ActionProxy把request请求传递给ActionInvocation
(8) ActionInvocation依次调用action和interceptor
(9) 根据action的配置信息,产生result
(10) Result信息返回给ActionInvocation
(11) 产生一个HttpServletResponse响应
(12) 产生的响应行为发送给客服端。
下面是流程图:
2.流程源码剖析:
1)StrutsPrepareAndExecuteFilter-> void init(FilterConfig filterConfig)方法进行初始化操作,并调用核心方法voiddoFilter(ServletRequest req, ServletResponse res, FilterChain chain),
在该方法中:
a. 处理了HttpServletRequest和HttpServletResponse;
b. 获取ActionMapping,ActionMapping: String name, String method, Stringextension, private Map<String, Object> params, private Result result;
c.整个框架最核心的方法:executeAction(request, response, mapping)
2)executeAction(request,response, mapping) -> serviceAction(request, response, mapping)serviceAction 询问ActionMapper调用相应的action处理该请求 -> 解析mapping中的参数,交给ActionProxy 来处理,通过代理模式执行ActionProxy
执行源码:
if (mapping.getResult() != null) {
Result result = mapping.getResult();
result.execute(proxy.getInvocation());
} else {
proxy.execute();
}
3)voidexecute(ActionInvocation invocation) -> Interceptor, action, result ->HttpServletResponse
3.在项目学习开发中,多个action可以采用动态方法调用:
1)通过设置method属性,method="相应的方法名";
2)通过感叹号,首先需要在strut2.xml中添加<constantname="struts.enable.DynamicMethodInvocation"value="true"></constant>,当请求/login!*.action时,就会调用相应的action;
3)通配符: actionname=*; result={1},第三种比较常用
4.Struts2使用json
当struts2返回json数据时,首先添加struts2-json-plugin依赖, 然后是在struts.xml中,在package中extends修改为extends="json-default" ,最后添加相应的<result name="json"type="json">
3.hibernate学习:
1.hibernate工作原理以及步骤:
a.读取并解析配置文件;
b.读取并解析映射信息,SessionFactory;
c.创建事物Transaction
d.持久化操作
e.提交事物
f.关闭Session
g.关闭SessionFactory
在项目开发中对于POJO的映射一般都会采用注解的方式进行映射。
2.hibernate的三种状态:
1)瞬时对象: 对于刚创建的一个对象,如果Session中和数据库中都不存在改对象,那么该对象就是瞬时对象;
2)离线对象: 离线对象就是数据库中存在该对象,但该对象有没有被session托管
3)持久化对象: 瞬时对象调用save方法,或者离线对象调用update方法变成持久化对象。即对改对象的任何修改,都会在提交事物时才会与之进行比较,如果不同则发送一个条update语句,否则就不会发送语句。
3.hibernate中的get方法和load方法的区别:
1)返回结果:
load方法查不到的话会抛出org.hibernate.ObjectNotFoundException异常;
get方法查不到的话会返回null。
2)查询机制上对比:
load方法会首先去Session缓存中查,查找到则返回,查找不到回判断是否为lazy(延迟加载),不是lazy会抛出异常,是lazy会先创建代理对象,当真正操作该对象时会访问数据库,查找不到抛出异常;
get方法会直接去数据库中查询,查找不到返回null
3)本质区别
load方法,hibernate会认为该对象一定在数据库中存在,可以放心使用代理对象来延迟加载,当真正操作该对象时才会访问数据库,查不到抛出异常;
get方法会先查缓存,没有查数据库,没有返回nul,get方法一定是返回的是实体对象。
4.hibernate3和hibernate4的稍微区别:
1)对于hibernate3的SessionFactory的属性参数bean配置使用的包是:org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;
对于hibernate4的SessionFactory的属性参数bean配置使用的包是:org.springframework.orm.hibernate4.LocalSessionFactoryBean
2)hibernate3中的获取的Session的getSession方法已经被摒弃
hibernate4中通过getSessionFactory().getCurrentSession()来获取一个Session
5.在项目开发中一般都让DaoImplement继承HibernateSupport,然后调用getHibernateTemplate(),使用封装好的简单CRUD
4.protobuf学习:
protobuf就是一种数据传输的方式,跟json一样可以取代xml来进行数据的传输,与json相比在大数据的条件下,protobuf数据压缩所在的大小优于json。
首先添加依赖:protobuf-java
测试:
protoc文件:
package tutorial;
option java_package="com.ssh.protobuftest.protobuf";
option java_outer_classname="PersonProbuf";
message Person{
required string name =1;
required int32 id=2;
optional string email=3;
enum PhoneType{
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber{
required string number=1;
optional PhoneType type=2[default = HOME];
}
repeated PhoneNumber phone=4;
message CountryInfo{
required string name=1;
required string code=2;
optional int32 number=3;
}
}
message AddressBook{
repeated Person person=1;
}
测试java代码:
import java.util.List;
import com.google.protobuf.InvalidProtocolBufferException;
import com.ssh.protobuftest.protobuf.PersonProbuf.Person;
import com.ssh.protobuftest.protobuf.PersonProbuf.Person.PhoneNumber;
public class TestPb {
public static void mian(String[] args) {
Integer a=new Integer(2);
a.equals(2);
//java_outer_classname.message name.Builder builder=java_outer_classname.messagename.newBuilder();
PersonProbuf.Person.Builder builder=PersonProbuf.Person.newBuilder();
//builder进行一系列的get/set方法
builder.setEmail("kkk@email.com");
builder.setId(1);
builder.setName("TestName");
builder.
//使用add是在一个message还有一个message,即类似内部类
//addxxx用来给内部message赋值,其中set可以连续set
addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().
setNumber("131111111").setType(PersonProbuf.Person.PhoneType.MOBILE));
builder.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().
setNumber("011111").setType(PersonProbuf.Person.PhoneType.HOME));
//调用build方法转换成message对象
Person person=builder.build();
//转成二进制流并保存在数组中
byte[] buf=person.toByteArray();
try {
Person person2 = PersonProbuf.Person.parseFrom(buf);
System.out.println(person2.getName() + ", " + person2.getEmail());
List<PhoneNumber> lstPhones = person2.getPhoneList();
for (PhoneNumber phoneNumber : lstPhones) {
System.out.println(phoneNumber.getNumber());
}
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
System.out.println(buf);
}
}
5.MySql性能优化学习:
1.优化方案:
1)建立索引,使用索引查询(类型,最好选择基本类型,eg: INT,建立的字段选择,选择修改少,查询多的字段);
2)sql语句优化,最好不要过多张表关联,少使用函数和%等导致索引失效的sql;
3)表结构(水平拆分,垂直拆分);
4)引擎选择;
5)使用缓存
6)主从结构(读写分离),主库抗写压力,通过从库来分担读压力,对于写少读多的应用。
2.因为mysql默认采用的是InnoDB,所以提高InnoDB的性能很有必要:
1)innodb_flush_log_at_trx_commit 设为2
当设为0,能使性能明显提升,但是不安全;
当设为1,每次插入数据时都会自定提都会刷新到磁盘中,性能低
同理set AUTOCOMMIT=0;
2)开启慢查询日志show.log
增加参数: log-queries-not-using-indexes 将所有没有走索引的sql都会记录到show.log中,方便找出没有使用索引的sql语句;
3)使用explian查看sql语句的执行形式,判断是否有走索引,访问的行数rows;
4)提高查询query_cache命中率;
5)关闭skip_name_resolve,减少逆向解析dns的消耗;
6)innodb_log_file_size 设为50%,对于高并发写入性能高,(太大recovery变慢,太小影响查询性能)
7)根据业务要求,考虑是否可关闭xa事务(分布式事务),有效减少磁盘刷新次数
8)反范式使用冗余字段,增加一些必要的冗余字段,以空间换时间增加开发的工作量和维护量
9)增加中间表,对需要经常联合查询的表,建立中间表以提高查询效率。通过建立中间表,把需要经常联合查询的数据插入到中间表中,然后将原来的联合查询改为对中 间表的查询,以此来提高查询效率。
10)垂直拆分,有时候有些字段使用频率很低或者字段的数据类型比较大,那么可以考虑垂直拆分的方法,把不常用的字段和大字段拆分出去,就是从业务角度来看,将 关联性不强的数据拆分到不同的instance上,从而达到消除瓶颈的目标。对于重复读类型比较多的场景,我们还可以加一层cache(缓存),来减少对DB的压力
11)水平拆分,水平拆分之后,任何实例都只有全量的1/n的数据,eg: 将userinfo拆分为3个cluster,每个cluster持有总量的1/3数据,3个cluster数据的总和等于一份完整 数据,但会给应用增加复杂度,它通常在查询时需要多个表名,查询所有数据需要union操作
下面是两张分布式计算的数据库框架图,顺便也呈现出来:
上述内容若有错误,欢迎各位拍砖指出,
更多推荐
所有评论(0)