HttpServletRequest + HttpServletResponse + poi-ooxml+SpringBoot異步

HttpServletResponse、HttpServletRequest

Web服務器收到每一次http請求,都會創建一個request對象、response對象。
request:        獲取客戶機提交過來的數據。
response:     向客戶機輸出數據。

四大作用域

從小到大順序爲:page  request  session  application
page:            頁面,只能作用於本網頁
request:        請求,只要不重定向,請求就會一直帶到下一個頁面
session:        會話,只要網頁不關閉,session就不會丟失
application:   應用,只要服務器不關閉,application就不會丟失

HttpServletRequest 

request獲取請求頭數據

long getDateHeader(String name)
String getHeader(String name):獲取指定名稱的請求頭;
Enumeration getHeaderNames():獲取所有請求頭名稱;
Enumeration getHeaders(String name):獲取指定請求頭名稱;
int getIntHeader(String name):獲取值爲int類型的請求頭。

request獲取請求相關的其它方法

int getContentLength()                    獲取請求體的字節數,GET請求沒有請求體,沒有請求體返回-1;
String getContentType()                   獲取請求類型,如果請求是GET,那麼這個方法返回null;如果是POST請求,那麼默認爲application/x-www-form-urlencoded,表示請求體內容使用了URL編碼;
String getMethod()                        返回請求方法,例如:GET
Locale getLocale()                        返回當前客戶端瀏覽器的Locale。java.util.Locale表示國家和言語,這個東西在國際化中很有用;
String getCharacterEncoding()             獲取請求編碼,如果沒有setCharacterEncoding(),那麼返回null,表示使用ISO-8859-1編碼;
void setCharacterEncoding(String code)    設置請求編碼,只對請求體有效!注意,對於GET而言,沒有請求體!!!所以此方法只能對POST請求中的參數有效!
String getContextPath()                   返回上下文路徑,例如:/hello
String getQueryString()                   返回請求URL中的參數,例如:name=zhangSan
String getRequestURI()                    返回請求URI路徑,例如:/hello/oneServlet
StringBuffer getRequestURL()              返回請求URL路徑,例如:http://localhost/hello/oneServlet,即返回除了參數以外的路徑信息;
String getServletPath()                   返回Servlet路徑,例如:/oneServlet
String getRemoteAddr()                    返回當前客戶端的IP地址;
String getRemoteHost()                    返回當前客戶端的主機名,但這個方法的實現還是獲取IP地址;
String getScheme()                        返回請求協議,例如:http;
String getServerName()                    返回主機名,例如:localhost
int getServerPort()                       返回服務器端口號,例如:8080
String getParameter(String name)          通過指定名稱獲取參數值;
String[] getParameterValues(String name)  通過指定名稱獲取參數值數組,有可能一個名字對應多個值,例如表單中的多個複選框使用相同的name時
Enumeration getParameterNames()           獲取所有參數的名字
Map getParameterMap()                     方法返回Map類型,對應所有參數。其中Map的key對應參數的名字;Map的value對應參數的值。
Map<String,String[]> map = request.getParameterMap();
Set<String> keys = map.keySet();
for(String key : keys){
String[] value = map.get(key);
System.out.println(key + " = " + value[0]);
}

GET請求和POST請求的區別

GET請求:
       Ø 請求參數會在瀏覽器的地址欄中顯示,所以不安全;
       Ø 請求參數長度限制長度在1K之內;
       Ø GET請求沒有請求體,無法通過request.setCharacterEncoding()來設置參數的編碼;
POST請求:
      Ø 請求參數不會顯示瀏覽器的地址欄,相對安全;
      Ø 請求參數長度沒有限制

最爲常見的客戶端傳遞參數方式有兩種(get/post)

l 瀏覽器地址欄直接輸入:一定是GET請求;
l 超鏈接:一定是GET請求;
l 表單:可以是GET,也可以是POST,這取決與<form>的method屬性值;

請求轉發和重定向
1:請求轉換是服務器內部跳轉,所有地址欄上的路徑不會改變; 重定向是瀏覽器在次發送請求,地址欄上的路徑會發生改變。
2:請求轉發只發送一次請求; 重定向會發送兩次請求。
3:請求轉發只能在當前應用內部跳轉; 重定向可以在內部跳轉也可以跳出當前應用。
4:請求轉發時,因爲是內部跳轉; 它的路徑寫法是 /資源路徑。重定向它的路徑需要寫 /工程名/資源路徑。
5:請求轉發,可以共享reqeust ; 重定向不可能,因爲每一次都是一個新的request。
6:請求轉換是通過reqeust發起  request.getRequestDispatcher().forward(); 重定向  response發起 response.sendRedirect()。

請求轉發

request.getRequestDispatcher("/success.html").forward(request,response);

HttpServletResponse

1.設置響應頭

可以使用response對象的setHeader()方法來設置響應頭!使用該方法設置的響應頭最終會發送給客戶端瀏覽器!
void setHeader(String name, String value)      設定指定名稱和值設置響應頭的名稱和內容
void setIntHeader(String name, int value)     設定 int 類型的值到 name 標頭
void setDateHeader(String name, long date)     使用指定名稱和值設置響應頭的名稱和內容
void addDateHeader(String name, long date)     添加指定名稱的響應頭和日期值
void addHeader(String name, String value)     添加指定名稱的響應頭和值
void addIntHeader(String name, int value)     添加指定名稱的響應頭和int值
boolean containsHeader(String name)             返回指定的響應頭是否存在
httpServletResponse.setHeader("content-type","text/html;charset=utf-8")
httpServletResponse.setHeader("Refresh","5;URL=http://www.baidu.com") 5秒後自動跳轉到百度

2.設置狀態碼

(1)httpServletResponse.setContentType("text/html;charset=utf-8")   等同與調用response.setHeader(“content-type”, “text/html;charset=utf-8”);
(2)httpServletResponse.setCharacterEncoding("utf-8"):             設置字符響應流的字符編碼爲utf-8;
(3)httpServletResponse.setStatus(200):                             設置狀態碼;
(4)httpServletResponse.sendError(404, "資源不存在")                當發送錯誤狀態碼時,Tomcat會跳轉到固定的錯誤頁面去,但可以顯示錯誤信息。

3.設置響應正文

response向客戶端響應有兩種響應流:字符響應流,字節響應流
(1)PrintWriter out = response.getWriter():獲取字符流;
(2)ServletOutputStream out = response.getOutputStream():獲取字節流;
在一個請求中不能同時使用這兩個流。不然會拋出IllegalStateException異常。
字符編碼:
httpServletResponse.getWriter()時默認字符編碼爲ISO-8859-1,可用httpServletResponse.setCharaceterEncoding("utf-8")來設置。
httpServletResponse.setContentType("text/html;charset=utf-8")    設置頭、正文。
httpServletResponse.setCharaceterEncoding("utf-8")               設置正文。

public void test(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse)throws Exception{
    String outputStreamData = "日拱一卒無永盡,功不唐捐總入海。";
    ServletOutputStream  servletOutputStream = httpServletResponse.getOutputStream();// 獲取輸出流
    // 通過設置響應頭控制瀏覽器以UTF-8的編碼顯示數據,如果不加這句話,那麼瀏覽器顯示的將是亂碼
    httpServletResponse.setHeader("content-type", "text/html;charset=UTF-8");
    // 將字符轉換成字節數組,指定以UTF-8編碼進行轉換
    byte[] dataByteArr = outputStreamData.getBytes("UTF-8");
    //使用OutputStream流向客戶端輸出字節數組
    servletOutputStream.write(dataByteArr);
    servletOutputStream.flush();
    servletOutputStream.close();

    String printWriterData = "日拱一卒無永盡,功不唐捐總入海。";
    httpServletResponse.setContentType("text/html;charset=utf-8");
    PrintWriter printWriter = httpServletResponse.getWriter(); // 獲取輸出流
    // 將字符轉換成字節數組,指定以UTF-8編碼進行轉換
    httpServletResponse.setHeader("Content-type",  "text/html;charset=UTF-8");
    printWriter.write(printWriterData);// 使用PrintWriter流向客戶端輸出字符
    printWriter.flush();
    printWriter.close();
}

4.重定向

(1).設置響應碼爲302,設置請求地址url: 
httpServletResponse.setStatus(302);
httpServletResponse.setHeader("Location", "http://www.baidu.com");
(2)
httpServletResponse.sendRedirect("http://www.baidu.com");

下載文件

以流的形式下載文件。
public HttpServletResponse download111(String path, HttpServletResponse response) {
	try {
		// path是指欲下載的文件的路徑。
		File file = new File(path);
		// 取得文件名。
		String filename = file.getName();
		// 取得文件的後綴名。
		String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();
		// 以流的形式下載文件。
		InputStream inputStream = new BufferedInputStream(new FileInputStream(path));
		byte[] buffer = new byte[inputStream.available()];
		inputStream.read(buffer);
		inputStream.close();
		// 清空response
		response.reset();
		// 設置response的Header
		response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
		response.addHeader("Content-Length", "" + file.length());
		OutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); // ServletOutputStream  ServletOutputStream
		response.setContentType("application/octet-stream");
		outputStream.write(buffer);
		outputStream.flush();
		outputStream.close();
	} catch (IOException ex) {
		ex.printStackTrace();
	}
	return response;
}

下載本地文件
public void downloadLocal(HttpServletResponse response) throws FileNotFoundException {
	String fileName = "demo.doc".toString(); // 文件的默認保存名
	// 讀到流中
	InputStream inputStream = new FileInputStream("D:/demo.doc");// 文件的存放路徑
	// 設置輸出的格式
	response.reset();
	response.setContentType("bin");
	response.addHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
	// 循環取出流中的數據
	byte[] bytes = new byte[100];
	int len;
	try {
		while ((len = inputStream.read(bytes)) > 0)
			response.getOutputStream().write(bytes, 0, len);
		inputStream.close();
	} catch (IOException e) {
		e.printStackTrace();
	}
}


下載網絡文件
public void downloadNet(HttpServletResponse response) throws MalformedURLException {
	int bytesum = 0;
	int byteread = 0;
	URL url = new URL("windine.blogdriver.com/logo.gif");
	try {
		URLConnection conn = url.openConnection();
		InputStream inStream = conn.getInputStream();
		FileOutputStream fs = new FileOutputStream("c:/abc.gif");
		byte[] buffer = new byte[1204];
		int length;
		while ((byteread = inStream.read(buffer)) != -1) {
			bytesum += byteread;
			System.out.println(bytesum);
			fs.write(buffer, 0, byteread);
		}
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
}

Excel操作(poi)

 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
	<dependency>
		<groupId>org.apache.poi</groupId>
		<artifactId>poi-ooxml</artifactId>
		<version>4.0.1</version>
	</dependency>

POI方法 -- Excel文件讀操作

public static void readExcel()throws Exception{
	String pathName="D:/XLS文件.xls";
	File file = new File(pathName);
	FileInputStream fileInputStream = new FileInputStream(file.getAbsolutePath());
	// .xls文件
	HSSFWorkbook hssfWorkbook = null;
	// .xlsx文件
	XSSFWorkbook xssfWorkbook = null;
	//表格(第一個 index=0)
	Sheet sheet = null;
	if(pathName.indexOf(".xlsx") >= 0){
		System.out.print("讀取xlsx文件");
		xssfWorkbook = new XSSFWorkbook(fileInputStream);
		sheet = xssfWorkbook.getSheetAt(0);
	}else{
		System.out.print("讀取xls文件");
		hssfWorkbook = new HSSFWorkbook(fileInputStream);
		sheet = hssfWorkbook.getSheetAt(0);
	}
	int firstRowNum = sheet.getFirstRowNum();
	int lastRowNum = sheet.getLastRowNum();
	//逐行遍歷
	for (int i = firstRowNum; i <= lastRowNum; i++) {
		Row row = sheet.getRow(i);
		if (row != null) {
			//判斷Cell不爲空
			for(Cell cell:row){
				if (cell!=null||!"".equals(cell)||cell.getCellType()!= CellType.BLANK||cell.getCellType() != CellType.ERROR) {
					CellType cellType=cell.getCellType();
					if(CellType.NUMERIC==cellType){
						//判斷日期類型
						if(HSSFDateUtil.isCellDateFormatted(cell)) {  //是
							Date cellDate = cell.getDateCellValue();
						  //  String cellValue = DateUtil.isCellDateFormatted(cell.getDateCellValue(),"yyyy-MM-dd");
						}else {  //否
							String  cellValue = new DecimalFormat("#.######").format(cell.getNumericCellValue());
							double number = cell.getNumericCellValue();
							System.out.println("第" + i + "行信息爲:" + number + " | ");
						}
					}else if(CellType.STRING==cellType){
						String str = cell.getStringCellValue();
						System.out.println("第" + i + "行信息爲:" + str + " | ");
					}else if(CellType.FORMULA==cellType){
						String str = cell.getCellFormula();
						System.out.println("第" + i + "行信息爲:" + str + " | ");
					}else if(CellType.BLANK==cellType){
						System.out.println(" 此格爲空 ");
					}else if(CellType.BOOLEAN==cellType){
						boolean flag = cell.getBooleanCellValue();
						System.out.println("第" + i + "行信息爲:" + flag + " | ");
					}else {
						System.out.print("錯誤類型");
					}
				}
			}

		}
	}
	hssfWorkbook.close();
	fileInputStream.close();
}

//Excel上傳
public void test001(HttpServletRequest httpServletRequest)throws Exception{
        MultipartHttpServletRequest multiPartRequest = (MultipartHttpServletRequest)httpServletRequest;
        MultipartFile multipartFile =multiPartRequest.getFile("file");
        InputStream inputStream = multipartFile.getInputStream();
        Workbook workbook = WorkbookFactory.create(inputStream);
        Sheet sheet = workbook.getSheetAt(0);
        
}

POI方法 -- Excel文件寫操作

public static void writeExcel()throws Exception {
		Workbook workbook;
		String excelStyle = "XLSX";
		String sheetName = "測試數據";
		String pathName = "D:/XLSX文件.xlsx";
		if (".XLS".equals(excelStyle.toUpperCase())) {
			workbook = new HSSFWorkbook();// .xls文件
		} else {
			workbook = new XSSFWorkbook();// .xlsx文件
		}
		// 生成一個表格,從0行開始。
		Sheet sheet = workbook.createSheet(sheetName);
		Row row = sheet.createRow(0);
		String[] titles = {"姓名", "密碼", "住址", "電話"};
		//創建表頭信息
		for (int i = 0; i < titles.length; i++) {
			Cell cell = row.createCell(i);
			cell.setCellValue(titles[i]);
		}
	   //編輯表格信息
		for (int i = 1; i < 10; i++) {//行
			row = sheet.createRow(i);
			for (int j = 0; j <titles.length; j++) {//列
				Cell cell = row.createCell(j);
				cell.setCellValue("要填入的信息");
			}
		}
		//寫入到文件中
		File file = new File(pathName);
		OutputStream outputStream = new FileOutputStream(file);
		workbook.write(outputStream);
		workbook.close();
		outputStream.close();
}

SpringBoot異步

必須用在public方法上(ServiceImpl裏)
在某異步方法的同一個類的其他方法調用此異步方法無效

簡單用法

激活Spring的異步: @EnableAsync 檢測@Async註解。

1。啓動類加@EnableAsync註解
@EnableAsync
@SpringBootApplication
public class Application {
    public static void main(String[] args){
        SpringApplication.run(Application.class, args);
    }
}

2.方法上加 @Async註解
@Component
public class AsyncTask {
    //不帶返回值
    @Async
    public void testDemoExecutor01(){
        System.out.println("testDemoExecutor01 thread name - " + Thread.currentThread().getName());
    }

    //帶返回值
    @Async
    public Future testDemoExecutor02() {
        System.out.println("testDemoExecutor02 thread name - " + Thread.currentThread().getName());
            User user = new User();
            user.setName("Jun");
            user.setAge("17");
            Thread.sleep(7000);
            return new AsyncResult(user);
    }
}

3.測試
@Test
public void testDemo() throws ExecutionException, InterruptedException {

    @Autowired
    private AsyncTask asyncTask;
	
	System.out.println("testDemo Thread in test class " + Thread.currentThread().getName());
	Future futureUser = asyncTask.ctestDemoExecutor02();
	futureUser.get();
}

配置類用法(無需在啓動類上加@EnableAsync註解)

1.創建配置類
@Configuration
@EnableAsync
public class SpringAsyncConfig {
    @Bean(name = "asyncUploadExcelExecutor")
    public Executor asyncUploadExcelExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor =  new ThreadPoolTaskExecutor();
        // 設置核心線程數
        threadPoolTaskExecutor.setCorePoolSize(5);
        // 設置最大線程數
        threadPoolTaskExecutor.setMaxPoolSize(10);
        // 設置隊列大小
        threadPoolTaskExecutor.setQueueCapacity(99999);
        // 設置線程池中線程名前綴
        threadPoolTaskExecutor.setThreadNamePrefix("async-upload-excel-");
        //當達到 MaxPoolSize 不再調用新線程,用調用者所在線程之星異步任務。
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return threadPoolTaskExecutor;
    }
    @Bean(name = "asyncDownExcelExecutor")
    public Executor asyncDownExcelExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor =  new ThreadPoolTaskExecutor();
        // 設置核心線程數
        threadPoolTaskExecutor.setCorePoolSize(5);
        // 設置最大線程數
        threadPoolTaskExecutor.setMaxPoolSize(15);
        // 設置隊列大小
        threadPoolTaskExecutor.setQueueCapacity(99999);
        // 設置線程池中線程名前綴
        threadPoolTaskExecutor.setThreadNamePrefix("async-down-excel-");
        //當達到 MaxPoolSize 不再調用新線程,用調用者所在線程之星異步任務。
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return threadPoolTaskExecutor;
    }
}

2.使用(一般在ServiceImpl的某些方法上)
public class demoServiceImpl{
	@Async("asyncUploadExcelExecutor")
	public void testAsyncExecutor04() {
		System.out.println("Execute uploadExcelExecutor executor - " + Thread.currentThread().getName());
	}
	
	@Async("asyncDownExcelExecutor")
	public void testAsyncExecutor05() {
		System.out.println("Execute downExcelExecutor executor - " + Thread.currentThread().getName());
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章