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();

图片校验码学习代码:(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);

}

 

/**

 37      * 使用指定源生成验证码

 38      * @param verifySize    验证码长度

 39      * @param sources   验证码字符源

 40      * @return

 41      */

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();

}

 

 /**

 56      * 生成随机验证码文件,并返回验证码值

 57      * @param w

 58      * @param h

 59      * @param outputFile

 60      * @param verifySize

 61      * @return

 62      * @throws IOException

 63      */

 

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;

}

 

/**

 71      * 输出随机验证码图片流,并返回验证码值

 72      * @param w

 73      * @param h

 74      * @param os

 75      * @param verifySize

 76      * @return

 77      * @throws IOException

 78      */

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;

}

 

/**

 86      * 生成指定验证码图像文件

 87      * @param w

 88      * @param h

 89      * @param outputFile

 90      * @param code

 91      * @throws IOException

 92      

 * @throws IOException */

 

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;

 

/**

 * Servlet implementation class CreateCodeServlet

 */

@WebServlet("/CreateCodeServlet")

public class CreateCodeServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

    public CreateCodeServlet() {

        super();

        // TODO Auto-generated constructor stub

    }

 

/**

 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

 */

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);

 

}

 

/**

 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

 */

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;

 

/**

 * Servlet implementation class VerifyCodeServlet

 */

@WebServlet("/VerifyCodeServlet")

public class VerifyCodeServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

       

    /**

     * @see HttpServlet#HttpServlet()

     */

    public VerifyCodeServlet() {

        super();

        // TODO Auto-generated constructor stub

    }

 

/**

 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)

 */

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);

}

}

 

/**

 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)

 */

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. 结果截图:
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值