数据的压缩

GzipOutputStream - > > ByteArrayOutputStream。

以下是在某个servlet中对指定的数据进行压缩

package cn.itcast.servlet;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GzipServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse resp)
throws ServletException, IOException {
//声明准备被压缩的数据
String str = "Hello你好Hello你好在内存中声明一Hello你好在" +
"内存中声明一个Hello你好在内存中声明一个Hello你" +
"好在内存中声明一个<br/>容器声明准备被压缩获取准备被压缩" +
"的数据的字节码的数据容器声明准备被压缩获取准备被压缩的数" +
"据的字节码的数据容器声明准备被压缩获取准备被压缩的数据的" +
"字节码的数据个容器声明准备被压缩获取准备被压缩的数据的字节码的" +
"数据在内存中声明一个容器声明准备被压缩获取准备被压缩的数据" +
"的字节码的数据";
//2:获取准备被压缩的数据的字节码
byte[] src = str.getBytes("UTF-8");
//3:在内存中声明一个容器
ByteArrayOutputStream destByte = new ByteArrayOutputStream();
//4:声明压缩的工具流,并设置压缩的目的地为destByte
GZIPOutputStream zip = new GZIPOutputStream(destByte);
//5:写入数据
zip.write(src);
//6:关闭压缩工具流
zip.close();
System.err.println("压缩之前字节码大小:"+src.length);
//7:获取压缩以后数据
byte[] dest = destByte.toByteArray();
System.err.println("压缩以后的字节码大小:"+dest.length);
//8:必须要输出压缩以后字节数组
resp.setContentType("text/html;charset=UTF-8");
//9:必须要使用字节流来输出信息
OutputStream out = resp.getOutputStream();
//10:通知浏览器。这是压缩的数据,要求浏览器解压
resp.setHeader("Content-encoding","gzip");
//11:通知浏览器压缩数据的长度
resp.setContentLength(dest.length);
//10:输出
out.write(dest);
} }

所有页面*.jsp全部压缩

只要是输出信息,只有两种方式:
    Response.getWriter()..输出信息――字符流。所有的jsp页面,编译后,都是通过JspWriter方式输出的信息。但所有jsp页面都是JspWriter,而jspwriter是对PrintWriter的包装。

Response.getOutputStream() ――字节流。

分析:如果要实现全站的压缩,请先实现对所有servlet中的resp.getWriter输出的数据都压缩先实现对一个进行压缩。

第一步:书写一个类Servlet类。正常输出信息
public class OneServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("Hello你好大家同学");
}
}
第二步:对这上面的这个类进行拦截-Filter,在拦截过程中包装response

实现抽像类:HttpServletResponseWrapper

package cn.itcast.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper; public class GzipFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//声明MyResponse包装类
MyResponse resp = new MyResponse((HttpServletResponse) response);
//放行时,必须要传递自己包装过的类
chain.doFilter(request, resp);
}
public void destroy() {
}
}
//实现对HttpSerlvetResponse的包装
class MyResponse extends HttpServletResponseWrapper{
public MyResponse(HttpServletResponse response) {
super(response);
}
}
第三步:为了可以压缩数据,我们必须要拦截getwriter方法

返回的不是apache的Wrtiter对象。。

package cn.itcast.filter;
public class GzipFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//声明MyResponse包装类
MyResponse resp = new MyResponse((HttpServletResponse) response);
//放行时,必须要传递自己包装过的类
chain.doFilter(request, resp);//第二步:这一段实现将数据写到a.txt中去。 //目标类调用完成了,返回 以后读取a.txt
File file = new File("d:/a/a.txt");//第三步:读取a.txt文件
//声明一个缓存的字符串对象
StringBuilder sb = new StringBuilder();
//读取文件
InputStream in = new FileInputStream(file);
byte[] b = new byte[1024];
int len = 0;
while((len=in.read(b))!=-1){
sb.append(new String(b,0,len,"UTF-8"));
}
in.close();
//转成字节开始压缩
byte[] src = sb.toString().getBytes("UTF-8");//第四步:压缩数据
//声明缓存容器
ByteArrayOutputStream destBytes = new ByteArrayOutputStream();
//声明压缩流
GZIPOutputStream gzip = new GZIPOutputStream(destBytes);
//压缩数据
gzip.write(src);
gzip.close();
//获取压缩以后数据
byte[] dest = destBytes.toByteArray();
System.err.println("压缩之前:"+src.length);
System.err.println("压缩以后:"+dest.length);
//输出
//必须要使用原生 的response
HttpServletResponse res = (HttpServletResponse) response;
res.setContentType("text/html;charset=UTf-8");
OutputStream out = res.getOutputStream();
res.setHeader("Content-encoding", "gzip");//必须
res.setContentLength(dest.length);
out.write(dest);
}
public void destroy() {
}
}
//实现对HttpSerlvetResponse的包装
class MyResponse extends HttpServletResponseWrapper{//第一步:声明包装类
public MyResponse(HttpServletResponse response) {
super(response);
}
@Override
public PrintWriter getWriter() throws IOException {
System.err.println("有人想获取输出流");
PrintWriter out = new PrintWriter(
new OutputStreamWriter(
new FileOutputStream("d:/a/a.txt"),"UTF-8"));
return out;
}
}
第四步:修改包装类Myresponse2,让输出数据放到一个内存缓存区中
package cn.itcast.filter;

public class GzipFilter2 implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
} public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse resp= (HttpServletResponse) response;
//声明包装类对象
MyResponse2 myresp = new MyResponse2(resp);
//放行,调用oneServlet.doGet
chain.doFilter(request, myresp); //第二步:从myresp2中读取原生的数据
byte[] src = myresp.getSrc(); //第三步:开始压缩
ByteArrayOutputStream destBytes = new ByteArrayOutputStream();
GZIPOutputStream zip = new GZIPOutputStream(destBytes);
zip.write(src);
zip.close(); //第三步:输出-使用原生的response
resp.setContentType("text/html;charset=UTF-8");
//获压缩以后数据
byte[] dest = destBytes.toByteArray();
System.err.println("压缩之前:"+src.length);
System.err.println("压缩以后:"+dest.length);
//设置头
resp.setContentLength(dest.length);
resp.setHeader("Content-Encoding","gzip");
//输出
OutputStream out = resp.getOutputStream();
out.write(dest); }
public void destroy() {
} }
//第一步:声明response的包装类
class MyResponse2 extends HttpServletResponseWrapper{
//将这个容器/a.txt,声明成员变量
private ByteArrayOutputStream srcByte;
public MyResponse2(HttpServletResponse response) {
super(response);
}
//修改增强getWtier方法
@Override
public PrintWriter getWriter() throws IOException {
srcByte = new ByteArrayOutputStream();
PrintWriter out =
new PrintWriter(
new OutputStreamWriter(srcByte, "UTF-8"));
return out;
}
//提供一个方法获取原生 的数据
public byte[] getSrc(){
return srcByte.toByteArray();
}
}
第五步:全部的jsp都要经过压缩

只要是通过包装rersponse,且修改了getWriter方法,返回一个自己的printwiter对象。声明一个放原数据的容器对象。就可以实现数据压缩。

public class GzipFilter2 implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
} public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse resp= (HttpServletResponse) response;
//声明包装类对象
MyResponse2 myresp = new MyResponse2(resp);
//放行,调用oneServlet.doGet
chain.doFilter(request, myresp); //第二步:从myresp2中读取原生的数据
byte[] src = myresp.getSrc(); //第三步:开始压缩
ByteArrayOutputStream destBytes = new ByteArrayOutputStream();
GZIPOutputStream zip = new GZIPOutputStream(destBytes);
zip.write(src);
zip.close(); //第三步:输出-使用原生的response
resp.setContentType("text/html;charset=UTF-8");
//获压缩以后数据
byte[] dest = destBytes.toByteArray();
System.err.println("压缩之前:"+src.length);
System.err.println("压缩以后:"+dest.length);
//设置头
resp.setContentLength(dest.length);
resp.setHeader("Content-Encoding","gzip");
//输出
OutputStream out = resp.getOutputStream();
out.write(dest); }
public void destroy() {
} }
//第一步:声明response的包装类
class MyResponse2 extends HttpServletResponseWrapper{
//将这个容器/a.txt,声明成员变量
private ByteArrayOutputStream srcByte;
private PrintWriter out;
public MyResponse2(HttpServletResponse response) {
super(response);
}
//修改增强getWtier方法
@Override
public PrintWriter getWriter() throws IOException {
srcByte = new ByteArrayOutputStream();
out =
new PrintWriter(
new OutputStreamWriter(srcByte, "UTF-8"));
return out;
}
//提供一个方法获取原生 的数据
public byte[] getSrc(){
if(out!=null){
out.close();
}
return srcByte.toByteArray();
}
}

配置如下:

<filter>
<filter-name>zip2</filter-name>
<filter-class>cn.itcast.filter.GzipFilter2</filter-class>
</filter>
<filter-mapping>
<filter-name>zip2</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>

同时实现对getoutputstream和getWriter压缩

在myrespons2这个类中,对getoutputstream也要覆盖。返回一个ServletOutputSteam的匿名对象。实现writer(int b)方法,将数据写到bytearrayoutputstream.

@Override
public ServletOutputStream getOutputStream() throws IOException {
srcByte = new ByteArrayOutputStream();
ServletOutputStream out = new ServletOutputStream() {
//所有IO最终都是一个个字节写出信息
@Override
public void write(int b) throws IOException {
System.err.println(">>>:"+b);
srcByte.write(b);//写到自己的缓存中去-相当于StringBuffer.append(""+b);
}
};
return out;
}
、用ThreadLocal管理事务

用三层模式:

Serlvet(MVC-C) – Sevice(服务层) – dao(数据访问层)

写两个dao,在service中调用这两个dao。

让第一个dao成功。让第二个dao失败,必须都回滚。

第一步:开发两个dao

public class UserDao2 {
public void save(){
String sql = "insert into users values(?,?,?)";
QueryRunner run = new QueryRunner();
try {
run.update(DataSourceUtils.getConn(),sql,"U002","Jack","333");
} catch (SQLException e) {
throw new RuntimeException(e);
} }
}

第二步:开发Service

public class UserService {
//声明两个dao
private UserDao1 dao1 = new UserDao1();
private UserDao2 dao2 = new UserDao2();
public void save(){
dao1.save();
dao2.save();
}
}

第三步:实现一个Servlet

public class UserServlet extends HttpServlet {
//声明service的实例
private UserService service = new UserService();
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
service.save();
}
}

第四步:修改datasourceutils.java

package cn.itcast.utils;
import java.sql.Connection;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DataSourceUtils {
// 声明线程局部的容器
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
private static DataSource ds;
static {
ds = // 默认的读取c3p0-config.xml中默认配置
new ComboPooledDataSource("itcast");
}
public static DataSource getDatasSource() {
return ds;
}
public static Connection getConn() {
// 先从tl这个容器中获取一次数据,如果当前线程已经保存过connection则直接返回这个connecton
Connection con = tl.get();
if (con == null) {
try {
con = ds.getConnection();// 每一次从ds中获取一个新的连接
//将这个con放到tl中
tl.set(con);
} catch (Exception e) {
e.printStackTrace();
}
}
return con;
}
}

第五步:声明一个过虑器在过虑器开始事务

package cn.itcast.filter;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import cn.itcast.utils.DataSourceUtils; public class TxFilter implements Filter{
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
//获取连接
Connection con = null;
//在try中开始事务
try{
con = DataSourceUtils.getConn();
//开始事务
con.setAutoCommit(false);
//放行
chain.doFilter(request, response);
//如果没有出错。
con.commit();
}catch(Exception e){
System.err.println("出错了");
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw new RuntimeException(e);
}finally{
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void destroy() {
}
}

第六步:将过虑器配置到weeb.xml中。且对某个路径设置过虑

<filter>
<filter-name>tx</filter-name>
<filter-class>cn.itcast.filter.TxFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>tx</filter-name>
<url-pattern>/tx/*</url-pattern>
</filter-mapping>

第七步:总结

在过虑器开始事务,就叫一种模式:OSIV模式》

OSIV – Open Session In View =- 打开与数据库的会话在View层。- Hibernate.—AOP

好处:长事务。可以在View层即找开事务。

不好处:当页面上有错误时也会回滚。解决:判断异常的类型。

第八步:优化:datasourceutls.java实现一个删除thredlocal中与线程相关的对象:

package cn.itcast.utils;
import java.sql.Connection;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DataSourceUtils {
// 声明线程局部的容器
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
private static DataSource ds;
static {
ds = // 默认的读取c3p0-config.xml中默认配置
new ComboPooledDataSource("itcast");
}
public static DataSource getDatasSource() {
return ds;
}
public static Connection getConn() {
// 先从tl这个容器中获取一次数据,如果当前线程已经保存过connection则直接返回这个connecton
Connection con = tl.get();
if (con == null) {
try {
con = ds.getConnection();// 每一次从ds中获取一个新的连接
//将这个con放到tl中
tl.set(con);
} catch (Exception e) {
e.printStackTrace();
}
}
return con;
}
public static void remove(){
tl.remove();
}
}

在TxFilter中调用一个remove:

public class TxFilter implements Filter{
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.err.println("thread:"+Thread.currentThread().getName());
//获取连接
Connection con = null;
//在try中开始事务
try{
con = DataSourceUtils.getConn();
//开始事务
con.setAutoCommit(false);
//放行
chain.doFilter(request, response);
//如果没有出错。
con.commit();
}catch(Exception e){
System.err.println("出错了");
try {
if(e instanceof SQLException){
con.rollback();
}else{
con.commit();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
throw new RuntimeException(e);
}finally{
try {
con.close();
DataSourceUtils.remove();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void destroy() {
}
}

在Java代码中调用Procedure

package cn.itcast.demo;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Types; import org.junit.Test; import cn.itcast.utils.DataSourceUtils; public class ProceDemo {
@Test
public void proc1() throws Exception{
//dbutils不提供调用存储过程的能力
Connection con = DataSourceUtils.getDatasSource().getConnection();
//获取调用过程的对象
CallableStatement cs =
con.prepareCall("{call proc1()}");
//执行
boolean boo = cs.execute();//如果返回true,指最后一句执行的是select语句
if(boo){
ResultSet rs = cs.getResultSet();
while(rs.next()){
System.err.println(rs.getString("name"));
}
}
con.close();
} @Test
public void proc2() throws Exception{
Connection con = DataSourceUtils.getDatasSource().getConnection();
//获取调用过程的对象
CallableStatement cs =
con.prepareCall("{call proc2(?,?)}");
cs.setString(1,"UAAA");
cs.setString(2, "王健");
boolean boo = cs.execute();
System.err.println(boo);
con.close();
} @Test
public void proc3() throws Exception{
Connection con = DataSourceUtils.getDatasSource().getConnection();
//获取调用过程的对象
CallableStatement cs =
con.prepareCall("{call proc5(?,?,?)}");
cs.setString(1,"UBDDB");
cs.setString(2, "张三");
cs.registerOutParameter(3,Types.INTEGER);//--int,
boolean boo = cs.execute();
System.err.println(">>:"+boo);//true
//从call中获取返回的值
int size = cs.getInt(3);
System.err.println("行数:"+size);
if(boo){
ResultSet rs= cs.getResultSet();
rs.next();
int ss = rs.getInt(1);
System.err.println("sss:"+ss);
}
con.close();
} @Test
public void proc6() throws Exception{
Connection con = DataSourceUtils.getDatasSource().getConnection();
//获取调用过程的对象
CallableStatement cs =
con.prepareCall("{call proc6(?,?,?,?)}");
cs.setString(1,"UBafadsB");
cs.setString(2, "张三");
cs.registerOutParameter(3,Types.INTEGER);//--int,
cs.registerOutParameter(4, Types.INTEGER);
boolean boo = cs.execute();
System.err.println(">>:"+boo);//faluse
//从call中获取返回的值
int size = cs.getInt(3);
int _s = cs.getInt(4);
System.err.println("行数:"+size+","+_s);
con.close();
}
}

过虑器 ThreadLocal 权限 监听器 观察者模式的更多相关文章

  1. 异步Servlet和异步过虑器

    异步处理功能可以节约容器线程.此功能的作用是释放正在等待完成的线程,是该线程能够被另一请求所使用. 要编写支持异步处理的 Servlet 或者过虑器,需要设置 asyncSupported 属性为 t ...

  2. muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor

    目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...

  3. java—过虑器基础(47)

    在web项目中就只有三大组件: Filter过虑器 监听器. Servlet 在web中过虑器就是一个类javax.servlet.Filter. 过虑器是用于在执行时,过虑用户的请求(request ...

  4. 【转】 AOP(面向切面编程)、Filter(过虑器)、Interceptor(拦截器)

    AOP(面向切面编程) 面向切面编程(AOP是Aspect Oriented Program的首字母缩写) ,我们知道,面向对象的特点是继承.多态和封装.而封装就要求将功能分散到不同的对象中去,这在软 ...

  5. Java基于Servlet过虑器

  6. Struts2使用拦截器完成权限控制示例

    http://aumy2008.iteye.com/blog/146952 Struts2使用拦截器完成权限控制示例 示例需求:    要求用户登录,且必须为指定用户名才可以查看系统中某个视图资源:否 ...

  7. 过虑器应用之1-设置request编码

    一:设置Post编码 post请求接收中文,需要在Servlet里写上 request.setCharacterEncoding("UTF-8"); 否则默认以iso-8859-1 ...

  8. 阶段5 3.微服务项目【学成在线】_day17 用户认证 Zuul_16-网关-过虑器

    4.5 过虑器 Zuul的核心就是过虑器,通过过虑器实现请求过虑,身份校验等. 4.5.1 ZuulFilter 自定义过虑器需要继承 ZuulFilter,ZuulFilter是一个抽象类,需要覆盖 ...

  9. 过滤器(Filter)、拦截器(Interceptor)、监听器(Listener)

    一.Filter 过滤器 1.简介 Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servle ...

随机推荐

  1. WinSCP列出’/’目录项出错

    无法获得目录列表 如图所示,使用百度云虚拟机时,FTP连接服务器,出现错提示,官方给出的说法是使用其他的FTP进行连接,但是之前成功连接过,查找资料后说是打开过png,mp3等媒体文件,切换路径时出错 ...

  2. 网站如何做到完全不需要jQuery

    jQuery是现在最流行的JavaScript工具库. 据统计,目前全世界57.3%的网站使用它.也就是说,10个网站里面,有6个使用jQuery.如果只考察使用工具库的网站,这个比例就会上升到惊人的 ...

  3. asp.net 后台 修改 javascript 变量

    Util.JSSetChange(Page, GetType()); public static void JSSetChange(Page page, Type cstype) { // Defin ...

  4. 浏览器兼容CSS代码:按钮文字垂直居中(input button text vertical align)

    经过测试的浏览器:IE6, IE7, IE8, IE9, Firefox, Chrome, Safiri, Maxthon 按钮的HTML代码: <input id="btn_comm ...

  5. RFC822DateGMT

    function RFC822DateGMT(dd: TDateTime): string; const Days:..] of string= ('Sun','Mon','Tue','Wed','T ...

  6. realloc() 用法详解

    原型:extern void *realloc(void *mem_address, unsigned int newsize); 语法:指针名=(数据类型*)realloc(要改变内存大小的指针名, ...

  7. WPF中利用DynamicDataDisplay快速实现示波器功能

    DynamicDataDisplay控件是一个功能很强的绘图工具,除了能生成曲线外,还有很多其他功能,具体见http://dynamicdatadisplay.codeplex.com/.这里你也能下 ...

  8. (转)Qt Model/View 学习笔记 (六)——在views中选择数据项

    在views中选择数据项 概念 用于新的view类中的选择模型比Qt3中的模型有了很大的改进.它为基于model/view架构的选择提供了更为全面的描述.尽管对提供了的views来说,负责操纵选择的标 ...

  9. 分享自lordinloft 《[转载]COMPILE_OPT 的用法介绍》

    来源:http://blog.sina.com.cn/s/blog_63180b75010117oj.html#bsh-73-372143085

  10. easy ui datagrid在没有数据时显示相关提示内容

    $(function () { $('#dg').datagrid({ fitColumns: true, url: 'product.json', pagination: true, pageSiz ...