1.新建一个javaweb项目

2.新建一个action包,用来写servlet

3.在action包里新建一个Servlet类名为CaptchaAction,仅重写service方法。

准备工作做完后,下面开始写代码:

response.setContentType("image/jpeg");  //告诉浏览器发送的是图片
BufferedImage image=new BufferedImage(130,30,BufferedImage.TYPE_INT_RGB);  //在缓存区创建一个图片,三个参数分别是图片的宽,高和颜色取值类型
Graphics2D g=(Graphics2D)image.getGraphics();  //拿到一个画家,其中Graphics2D是Graphics的子类,功能比Graphics要强,因此强转一下
g.setColor(Color.WHITE);  //设置填充颜色为白色
g.fillRect(0,0,image.width(),image.height());  //画一个填充矩形,四个参数的含义是起始点x坐标,y坐标,终止点x坐标,y坐标
g.setColor(Color.BLACK);  //设置颜色为黑色
g.drawRect(0, 0, image.getWidth()-1, image.getHeight()-1)  //绘制一个矩形为边框,四个参数含义同填充矩形
String sn=randomString(4);  //随机一个字符串,这个方法是自定义方法,方法体在后边
//绘制验证码
g.setFont(new Font("微软雅黑",Font.BLOD,20));  //设置字体,参数为Font类型,new一个Font,三个参数分别是字体,样式(加粗或倾斜),字体大小
for(int i=0;i<sn.length;i++){  //循环在图片上画取出的字符
  g.setColor(randomColor());  //每次画之前随机一个颜色,randoColor()是自定义随机颜色的方法,方法体在后边
  int deg=randomDeg();    
  double d=Math.PI*deg/180;  //获取一个随机度数,转为弧度制
  g.rotate(d,15+30*i,15);    //每次都以当前字符中心为坐标原点,随机旋转一个度数
  g.drawString(sn.charAt(i)+"",13+30*i,25);  //画出当前字符,每次画字符的位置不能重复
  g.rotate(d*-1,15+30*i,15);  //画完当前字符之后要把画布旋转回来
}
for(int i=0;i<10;i++0{  //随机十条干扰线
  Random random=new Random();
  g.setColor(randomColor);  
  int x1=random.nextInt(image.getWidth());
			  int y1=random.nextInt(image.getHeight());
			  int x2=random.nextInt(20)-10+x1;
			  int y2=random.nextInt(20)-10+y1;
			  g.drawLine(x1, y1, x2, y2);  //画线,四个参数是起始点x坐标,y坐标,终点x坐标,y坐标}
for(int i=0;i<50;i++) {  //随机50个干扰点
			  Random random=new Random();
			  g.setColor(randomColor());
			  int x1=random.nextInt(image.getWidth());
			  int y1=random.nextInt(image.getHeight());
			  int x2=x1;
			  int y2=y1;
			  g.drawLine(x1, y1, x2, y2);  //画点,当线的起始点和终点是同一个点时,是一个点
		}
		ImageIO.write(image, "jpeg", response.getOutputStream());  //将画好的图片发给浏览器service方法体书写完毕。
附service方法中用到的一些自定义方法:
//随机字符串方法
private String randomString(int length){  //传一个int,定义取出字符的数量
  Random random=new Random();  //new一个随机函数
  String str="1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM";  //定义一个字符串
  String sn="";  //定义一个空字符串用来保存随机结果
length;i++){
    int index=random.nextInt(str.length);  //随机一个下标,数字大小不超过str字符串长度
    sn+=str.charAt(index);  //通过下标取得相应字符,保存在sn中
  }
  return sn;  //返回sn
}
//获取随机颜色方法
private Color randomColor(){
  Random random=new Random();  
  Color color=new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255));  //new一个color,参数为三个,RGB颜色命名法,随机数大小不超过255
  return color;
}
//获取随机度数方法
private int randomDeg() {
		  int [] arr= {1,-1};  //定义一个新数组,仅有1,-1两个数,用来调整度数的正负值,让随机出来的验证码左右都能倾斜
		  Random random=new Random();
		  return (15+random.nextInt(25))*arr[random.nextInt(2)];
	}