天天看點

java.lang.IllegalStateException: getWriter() has already been called for this response問題解決和java圖形驗證碼java.lang.IllegalStateException: getWriter() has already been called for this response問題解決

java.lang.IllegalStateException: getWriter() has already been called for this response問題解決

在做圖檔驗證碼的是後遇到這個問題!

java.lang.IllegalStateException: getWriter() has already been called for this response問題解決和java圖形驗證碼java.lang.IllegalStateException: getWriter() has already been called for this response問題解決

異常産生原因:web容器生成的servlet代碼中有out.write(""),這個和JSP中調用的response.getOutputStream()産生沖突.即Servlet規範說明,不能既調用response.getOutputStream(),又調用response.getWriter(),無論先調用哪一個,在調用第二個時候應會抛出IllegalStateException,因為在jsp中,out變量實際上是通過response.getWriter得到的,你的程式中既用了 response.getOutputStream,又用了out變量,故出現以上錯誤。

解決:添加一個語句

response.reset();

java.lang.IllegalStateException: getWriter() has already been called for this response問題解決和java圖形驗證碼java.lang.IllegalStateException: getWriter() has already been called for this response問題解決

圖檔校驗碼學習代碼:(eclipse 環境測試)

參考(轉自):https://www.cnblogs.com/h--d/p/8258610.html

  1. 生成校驗碼的工具類:

package com.kk.utils;

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.RenderingHints;

import java.awt.geom.AffineTransform;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStream;

import java.util.Arrays;

import java.util.Random;

import javax.imageio.ImageIO;

public class VerifyCodeUtils {

//使用到Algerian字型,系統裡沒有的話需要安裝字型,字型隻顯示大寫,去掉了1,0,i,o幾個容易混淆的字元

public static final String VERIFY_CODE = "23456789ABCDEFGHIJKLMNPQRSTUVWXYZ";

private static Random random = new Random();

//使用系統預設字元源生成驗證碼

//verifySize: 驗證碼長度

public static String generateVerifyCode(int verifySize) {

return generateVerifyCode(verifySize,VERIFY_CODE);

}

private static String generateVerifyCode(int verifySize, String verifyCode) {

if(verifyCode == null || verifyCode.length() == 0) {

verifyCode = VERIFY_CODE;

}

int codesLen = verifyCode.length();

Random random = new Random(System.currentTimeMillis());

StringBuilder verifyCode1 = new StringBuilder(verifySize);

for(int i= 0;i<verifySize;i++) {

verifyCode1.append(verifyCode.charAt(random.nextInt(codesLen-1)));

}

return verifyCode1.toString();

}

public static String outputVerifyImage(int w,int h,File outputFile,int verifySize)throws IOException {

String verifyCode = generateVerifyCode(verifySize);

outputImage(w,h,outputFile,verifyCode);

return verifyCode;

}

public static String outputVerifyImage(int w,int h,OutputStream os,int verifySize)throws IOException  {

String verifyCode = generateVerifyCode(verifySize);

outputImage(w, h, os, verifyCode);

return verifyCode;

}

public static void outputImage(int w, int h, File outputFile, String verifyCode) throws IOException {

// TODO Auto-generated method stub

if(outputFile == null) {

return;

}

File dir = outputFile.getParentFile();

if(dir.exists()) {

dir.mkdirs();

}

try {

outputFile.createNewFile();

FileOutputStream fos = new FileOutputStream(outputFile);

outputImage(w, h, fos, verifyCode);

fos.close();

} catch (IOException e) {

throw e;

}

}

public static void outputImage(int w, int h, OutputStream os, String code) throws IOException {

// TODO Auto-generated method stub

int verifySize = code.length();

BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);

Random rand = new Random();

Graphics2D g2 = image.createGraphics();

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING

                 , RenderingHints.VALUE_ANTIALIAS_ON);

Color[] colors = new Color[5];

Color[] colorSpaces = new Color[] {Color.WHITE, Color.CYAN,

           Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE,

           Color.PINK, Color.YELLOW };

float[] fractions = new float[colors.length];

for(int i=0;i<colors.length;i++) {

colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)];

fractions[i] = rand.nextFloat();

}

Arrays.sort(fractions);

g2.setColor(Color.DARK_GRAY); //設定邊框

g2.fillRect(0, 0, w, h);

Color c = getRandColor(200,250);

g2.setColor(c);        //設定背景顔色         

g2.fillRect(0, 2, w, h-4);

//繪制幹擾線條

Random random = new Random();

g2.setColor(getRandColor(160, 200));

for(int i=0;i<20;i++) {

int x = random.nextInt(w-1);

int y = random.nextInt(h-1);

int x1 = random.nextInt(6)+1;

int y1 = random.nextInt(12)+1;

g2.drawLine(x, y, x+x1+40, y+y1+20);

}

// // 添加噪點

float yawpRate = 0.0f; //噪聲率

int area = (int) (yawpRate*w*h);

for(int i=0;i<area;i++) {

 int x = random.nextInt(w);

 int y = random.nextInt(h);

 int rgb = getRandomIntColor();

 image.setRGB(x, y, rgb);

}

shear(g2, w, h, c);// 使圖檔扭曲

g2.setColor(getRandColor(100, 160));

int fontSize = h-4;

Font font = new Font("Algerian", Font.ITALIC,fontSize);

g2.setFont(font);

char[] chars = code.toCharArray();

for(int i = 0; i < verifySize; i++) {

AffineTransform affine = new AffineTransform();

affine.setToRotation(Math.PI/4*rand.nextDouble()* (rand.nextBoolean() ? 1 : -1), (w / verifySize) * i + fontSize/2, h/2);

g2.setTransform(affine);

g2.drawChars(chars, i,1, ((w-10) / verifySize) * i + 5, h/2 + fontSize/2 - 10);

}

g2.dispose();

ImageIO.write(image, "PNG", os);

}

private static Color getRandColor(int fc, int bc) {

// TODO Auto-generated method stub

if(fc>255) {

fc = 255;

}

if(bc > 255) {

bc = 255;

}

int r = fc + random.nextInt(bc - fc);

int g = fc + random.nextInt(bc - fc);

int b= fc + random.nextInt(bc - fc);

return new Color(r,g,b);

}

private static int getRandomIntColor() {

int[] rgb = getRandomRgb();

int color = 0;

for(int c: rgb) {

color = color <<8;

color = color | c;

}

return color;

}

private static int[] getRandomRgb(){

int[] rgb = new int[3];

for(int i =0;i<3;i++) {

rgb[i] = random.nextInt(255);

}

return rgb;

}

 private static void shear(Graphics g, int w1, int h1, Color color) {

 shearX(g, w1, h1, color);

 shearY(g, w1, h1, color);

}

private static void shearX(Graphics g, int w1, int h1, Color color) {

// TODO Auto-generated method stub

int period = random.nextInt(2);

boolean borderGap = true;

int frames = 1;

int phase = random.nextInt(2);

for(int i = 0;i < h1; i++) {

double d = (double) (period >>1)

* Math.asin((double) i / (double)period

+(6.2831853071795862D * (double) phase)

   / (double) frames);

g.copyArea(0, i, w1, 1, (int)d, 0);

if(borderGap) {

g.setColor(color);

g.drawLine((int)d, i, 0,i);

g.drawLine((int)d+w1,i , w1, i);

}

}

}

private static void shearY(Graphics g, int w1, int h1, Color color) {

// TODO Auto-generated method stub

int period = random.nextInt(40) + 10;

boolean borderGap = true;

int frames = 20;

int phase = 7;

for(int i = 0;i<w1;i++) {

double d = (double) (period >> 1)

* Math.sin((double) i / (double) period

+ (6.2831853071795862D * (double) phase)

/ (double) frames);

g.copyArea(i, 0, 1, h1, 0, (int) d);

if (borderGap) {

g.setColor(color);

g.drawLine(i, (int) d, i, 0);

g.drawLine(i, (int) d + h1, i, h1);

}

}

}

public static void main(String[] args) throws IOException{

File dir = new File("G:/圖形校驗碼/");

int w = 200, h = 80;

String verifyCode = generateVerifyCode(4);

File file = new File(dir, verifyCode + ".jpg");

outputImage(w, h, file, verifyCode);

System.out.println("圖形校驗碼生成成功");

}

}

  1. 産生驗證碼servlet的源碼:

   package com.kk.code;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.kk.utils.VerifyCodeUtils;

@WebServlet("/CreateCodeServlet")

public class CreateCodeServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

    public CreateCodeServlet() {

        super();

        // TODO Auto-generated constructor stub

    }

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// TODO Auto-generated method stub

//response.getWriter().append("Served at: ").append(request.getContextPath());

response.setContentType("text/html; charset=UTF-8");

PrintWriter out = response.getWriter();

response.setHeader("Pragma", "No-cache");  

response.setHeader("Cache-Control", "no-cache");  

response.setDateHeader("Expires", 0);  

response.setContentType("image/jpeg");  

 //生成随機字串  

 String verifyCode = VerifyCodeUtils.generateVerifyCode(4);

 out.print(verifyCode);

  //存入會話session  

 request.getSession().setAttribute("CODE", verifyCode.toLowerCase());  

 //生成圖檔  

 int width = 100;//寬

 int height = 40;//高  

 response.reset();

 VerifyCodeUtils.outputImage(width, height, response.getOutputStream(), verifyCode);

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// TODO Auto-generated method stub

doGet(request, response);

}

}

  1. 校驗前端輸入的驗證碼的servlet源碼:

  package com.kk.code;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

@WebServlet("/VerifyCodeServlet")

public class VerifyCodeServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

    public VerifyCodeServlet() {

        super();

        // TODO Auto-generated constructor stub

    }

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// TODO Auto-generated method stub

response.getWriter().append("Served at: ").append(request.getContextPath());

response.setContentType("text/html; charset=UTF-8");

PrintWriter out = response.getWriter();

String code = request.getParameter("code");

out.println("code="+code);

String key = (String) request.getSession().getAttribute("CODE");

if(code != null && code.equalsIgnoreCase(key)){

request.getSession().removeAttribute("CODE");

response.getWriter().println(true);

}else{

response.getWriter().println(false);

}

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// TODO Auto-generated method stub

doGet(request, response);

}

}

  1. 前端頁面jsp源碼:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>My JSP 'ImageCode.jsp' starting page</title>

<meta http-equiv="pragma" content="no-cache">

<meta http-equiv="cache-control" content="no-cache">

<meta http-equiv="expires" content="0">    

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

<meta http-equiv="description" content="This is my page">

<!--

<link rel="stylesheet" type="text/css" href="styles.css">

-->

  </head>

  <body>

  <h2>測試驗證碼:</h2>

     請輸入驗證碼:<input type="text" name="code" /><img id="codeimg"

      src="${pageContext.request.contextPath }/CreateCodeServlet" 

      onclick="changeImg()"><a href="javascript:void(0);" onclick="changeImg()">

      看不清,換一張</a>

     <button onclick="submit()">送出</button>

     <script type="text/javascript">

         //改變驗證碼事件

         function changeImg(){

              alert("nihao");

             var img = document.getElementById('codeimg');

             img.src = "${pageContext.request.contextPath }/CreateCodeServlet?x=" + Math.floor(Math.random()*100)

         }

         //送出驗證并驗證驗證碼

         function submit(){

             var input = document.getElementsByTagName('input')[0];

             var val = input.valueOf();

             alert("input="+input.value);

             //ajax送出

             var xhr = new XMLHttpRequest();

             xhr.onreadystatechange = function(){

                 if(xhr.readyState == 4 && xhr.status == 200) {

                     alert(xhr.responseText);

                }  

            }             

             xhr.open('get','${pageContext.request.contextPath }/VerifyCodeServlet?code=' + input.value);

             xhr.send(null);

         }

     </script>

  </body>

</html>

  1. 結果截圖:
  2. java.lang.IllegalStateException: getWriter() has already been called for this response問題解決和java圖形驗證碼java.lang.IllegalStateException: getWriter() has already been called for this response問題解決