Stream类分析

先认识一个概念:流
流是数据流向某个对象,并且到达这个对象的过程
流式输入/输出是一种很常见的输入和输出方式。认识这一个概念,需要我们用使用、认识计算机的角度,如:输入流代表从外设(比如键盘)流入计算机内存的数据序列;输出流代表从计算机内存流向外设(比如显示器)的数据序列

根据数据类型的不同,流分为两类:字节流(Byte流),可以依次读写8位二进制数,如 InputStream 和 OutputStream 类;字符流(Character流),可以一次读写16位二进制数,如 Reader 和 Writer

他们都是抽象类。下面看看他们的结构层次:

InputStream 类层次结构图

 

OutputStream 类层次结构图
Reader类层次结构图
Writer类层次结构图

 

单例、多例与线程安全问题

单例与多例问题是指,当多个用户访问某个类时,系统是为每个用户创建一个该类实例,还是整个系统无论多少用户访问,只创建一个该类实例。

线程安全问题是指,多个用户同时在访问同一个程序时,其对于某一数据的修改,会不会影响到其他用户中的该数据。若无影响,则是线程安全的;若有可能影响,则是线程不安全的。

现在对HttpServlet、HttpSession、Struts2中的Action、Hibernate中的SessionFactory与Session,进行总结。

(1)HttpServlet
单例。即无论多少用户访问同一个业务,如LoginServlet,Web容器只会创建一个该Servlet实例。而该实例是允许多用户访问的。
若Servlet中包含成员变量,则每个用户对于成员变量的修改,均会影响到其他用户所看到的该变量的值,所以这时是线程不安全的。若不包含成员变量,则是线程安全的。

(2)HttpSession
多例。Web容器会为每个用户开辟一个Session,多个用户会有多个Session。而每个用户只能访问自己的Session。所以,对于Session来说,就不存在并发访问的情况,也就不存在线程安全的问题了。所以可以说是线程安全的。

(3)Struts2的Action
多例。对于同一个业务,例如LoginAction,系统会为每一个用户创建一个LoginAction的实例,并使其成员变量username与password接收用户提交的数据。同一用户只能访问自己的Action。所以,对于Action来说,就不存在并发访问的情况,也就不存在线程安全的问题了。所以可以说是线程安全的。

(4)Hibernate的SessionFactory
单例。无论多少用户访问该项目,系统只会创建一个SessionFactory对象,即这个对象是可以被所有用户访问的。
SessionFactory实现类中所包含的成员变量基本都是final常量,即任何用户均不能修改。所以,也就不存在用户的修改对其他用户的影响问题了,所以是线程安全的。

(5)Hibernate的Session
多例。系统会为每个用户创建一个Session。
Session的实现类中定义了很多的非final成员变量,一个事务对成员变量所做的修改,会影响到另一个事务对同一数据的访问结果,所以是线程不安全的。

Struts2接受请求参数

先来几句题外话:很多大佬都说Struts2存在安全问题,已经过时啦,可以直接入手Spring Boot~Spring Cloud之类的,有入手尝试SpringBoot确实开放效率会高很多,非常便捷。但是滴滴滴本来就是个菜鸡啊,有很多东西其实还是想经历一遍,然后达到螺旋式的上升。温故而知新,希望在10月秋招中得到橄榄枝~~~

关于Struts2接收请求参数,滴滴滴将记录下四种方式:

属性驱动方式
域驱动方式
集合数据接收
ModelDriver 方式

属性驱动方式是指服务器接受来自客户端离散数据的方式。用户提交的数据,Action原封不动的进行逐个接收。这种接收方式的要求是:在Action类中定义与请求参数同名的属性,需要定义该属性的set方法,这样能满足Action自动将请求参数的值赋予同名属性

举例如下:

1.在某一jsp文件body中写入form表单

<form action="test/register.action" method="post">
姓名:<input type="text" name="name"/><br>
年龄:<input type="text" name="age"/><br>
<input type="submit" value="注册"/>
</form> 

2.编写form表单中指定的action

public class RegisterAction{

    private String name;
    private int age;
    //getter and setter

    public String execute(){
         System.out.println("你好" + username);
         System.out.println("你好" + password);
          return "success";
    }

}

3.在web.xml中注册action可用,默认执行execute方法

<package name="滴滴滴" namespace="/test" extends="struts-default">
   <action name="register" class="action.Register">
   <result>/success.jsp</result>
   </action>
</package>

4.编写目标success.jsp接收数据页面

<body>
     姓名 = ${name}<br>
     年龄 = ${age}
</body>

下面我们来着重讲一下域驱动,并且分析执行过程

域驱动方式指,服务器端以封装好的对象方式接收自客户端的数据。将用户提交的多个数据以封装对象的方式进行整体接收。该方式的实现要求:表单提交时,参数以对象属性的方式提交。在Action中要将同名的对象定义为属性。这样请求将会以封装好的对象数据形式提交给Action。

定义POJO:

public class Student{
   private String name;

    private int age;
    //getter and setter
}

编写jsp,提交form表单到action:

<form action="test/register.action" method="post">

姓名:<input type="text" name="student.name"/><br>


年龄:<input type="text" name="student.age"/><br>


<input type="submit" value="注册"/>


</form>
 

编写action:

             public class RegisterAction{

                 private Student student;
                 //getter and setter

                 public String execute(){
                       return "success";
                 }

             }

在struts.xml中注册action:

<package name="滴滴滴" namespace="/test" extends="struts-default">
      <action name="register" class="actions.RegisterAction">
           <result>/success.jsp</result>
      </action>
</package>

编写success.jsp:

<body>
    姓名 = ${student.name}<br>
    年龄 = ${student.age}<br>
</body>

下面来分析下对象类型数据接收的内部执行顺序:

(1)当将表单请求提交给服务器后,服务器首先会解析出表单元素,并读取其中的一个元素name值,读取如下:

    姓名:<input type="text" name="student.name"/><br>

(2)执行Action的getStudent()方法以获取Student对象。判断Student对象是否为null,若为null,则服务器会通过反射创建一个Student对象。

(3)由于此时的Student对象为null,所以系统会创建一个并调用setStudent()方法将student初始化。

(4)此时的student已非空,会将刚才解析出的表单元素,通过调用其set方法,这里是setName()方法,将用户输入的值初始化该属性。

(5)再解析下一个表单元素,并读取其name值。

  年龄:<input type="text" name="student.age"/><br>

(6)再次执行Action的getStudent()方法以获取Student对象。此时的Student对象已非空。

(7)将刚才解析出的表单元素,通过调用其set方法,这里是setAge()方法,将用户输入的值初始化该属性。

 

 

 

 

 

 

 

 

 

 

 

关于SSH框架集成中出现的failed to lazily initialize a collection of role could not initialize proxy – no session异常解决办法

 

异常信息截图如下:这是滴滴滴近期在学习csdn博客 博主倪升武的SSH项目中,出现的一个问题,在easyUI——Action——Service——DB的数据查询阶段,能正常打印得到的数据库结果,在数据返回中,页面无结果显示,打开chrome查看详情如下:failed to lazily initialize a collection of role could not initialize proxy – no session。判断为hibernate出现问题。

hibernate懒加载报错

 

我的解决办法为:在web.xml中通过filter配置扩大session作用范围,注意要设置在struts的上方。

扩大Session作用范围

根据其他的网络资料称,可以在model中取消懒加载,滴滴滴测试了下,此项目内是无效的,而且取消懒加载并非是最佳解决方案。