前端:利用ExtJs的autoEl功能加載圖片。
1 var imgCheckValid = new Ext.create('Ext.Component',{ 2 width: 70, //圖片寬度 3 height: 45, //圖片高度 4 margin:'5', 5 id:"imd_imgCheckValid", 6 autoEl: { 7 tag: 'img', //指定為img標簽 8 src: 'Code/genCodeImg.do?' //指定url路徑 9 }, 10 listeners: { 11 render: function(component){ 12 component.getEl().on('click', function(e){ 13 this.dom.src = 'Code/genCodeImg.do?'+(new Date().getTime()); // autoEl不會自動加載,只有設置了不同的src才會加載 14 }); 15 } 16 } 17 });
小編心得:autoEl會自動加載,要實現點擊驗證碼刷新,登錄失敗刷新,方法是給請求的url加上時間戳。所以刷新驗證碼只要在需要刷新的時候重新設置加上時間戳的src即可。
疑問解答:為什麼只是給了src一個路徑,並沒有給圖片地址,頁面能顯示圖片呢?
目前不是很清楚:猜想它是根據給的鏈接,自動從response中獲得二進制資源。明確的是我會向response中寫入流
後台:struts,spring配置
struts:
1 <!-- 客戶端 --> 2 <package name="Code" extends="json" namespace="/Code"> 3 <action name="genCodeImg" class="codeAction" method="genCodeImg"> 4 <result name="success" type="json"> 5 <param name="root">responseJson</param> 6 </result> 7 </action> 8 </package>
spring:
1 <!-- 驗證碼生成器--> 2 <bean id="codeAction" class="com.sinsche.i.action.impl.CodeAction" 3 scope="prototype"></bean>
後台:
1 import java.awt.Color; 2 import java.awt.Font; 3 import java.awt.Graphics; 4 import java.awt.image.BufferedImage; 5 import java.util.Map; 6 import java.util.Random; 7 8 import javax.imageio.ImageIO; 9 import javax.servlet.ServletOutputStream; 10 import javax.servlet.http.HttpServletResponse; 11 12 import org.apache.struts2.ServletActionContext; 13 14 import com.common.core.st2.action.BaseAction; 15 import com.opensymphony.xwork2.ActionContext; 16 import com.sinsche.i.action.ICodeAction; 17 18 public class CodeAction extends BaseAction implements ICodeAction { 19 /** 20 * 21 */ 22 private static final long serialVersionUID = 6865491407475710154L; 23 private boolean success; 24 private String message; 25 // 圖片的寬度。 26 private int width = 70; 27 // 圖片的高度。 28 private int height = 45; 29 // 驗證碼字符個數 30 private int codeCount = 4; 31 // 驗證碼干擾線數 32 private int lineCount = 20; 33 // 驗證碼圖片Buffer 34 private BufferedImage buffImg = null; 35 Random random = new Random(); 36 public String genCodeImg() throws Exception { 37 HttpServletResponse resp = ServletActionContext.getResponse(); 38 int fontWidth = width / codeCount;// 字體的寬度 39 int fontHeight = height - 5;// 字體的高度 40 int codeY = height - 8; 41 42 // 圖像buffer 43 buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 44 Graphics g = buffImg.getGraphics(); 45 // Graphics2D g = buffImg.createGraphics(); 46 // 設置背景色 47 g.setColor(getRandColor(200, 250)); 48 g.fillRect(0, 0, width, height); 49 50 // 設置字體 51 // Font font1 = getFont(fontHeight); 52 Font font = new Font("Fixedsys", Font.BOLD, fontHeight); 53 g.setFont(font); 54 55 // 設置干擾線 56 for (int i = 0; i < lineCount; i++) { 57 int xs = random.nextInt(width); 58 int ys = random.nextInt(height); 59 int xe = xs + random.nextInt(width); 60 int ye = ys + random.nextInt(height); 61 // g.setColor(getRandColor(1, 255)); 62 shear(g,1,20,getRandColor(1, 255)); 63 g.drawLine(xs, ys, xe, ye); 64 } 65 66 // 添加噪點 67 float yawpRate = 0.01f;// 噪聲率 68 int area = (int) (yawpRate * width * height); 69 for (int i = 0; i < area; i++) { 70 int x = random.nextInt(width); 71 int y = random.nextInt(height); 72 73 buffImg.setRGB(x, y, random.nextInt(255)); 74 } 75 76 String str1 = randomStr(codeCount);// 得到隨機字符 77 for (int i = 0; i < codeCount; i++) { 78 String strRand = str1.substring(i, i + 1); 79 g.setColor(getRandColor(1, 255)); 80 // g.drawString(a,x,y); 81 // a為要畫出來的東西,x和y表示要畫的東西最左側字符的基線位於此圖形上下文坐標系的 (x, y) 位置處 82 83 g.drawString(strRand, i * fontWidth + 3, codeY); 84 } 85 86 // 將四位數字的驗證碼保存到Session中。 87 Map<String, Object> map = ActionContext.getContext().getSession(); 88 System.out.print(str1); 89 map.put("code", str1.toString()); 90 // 禁止圖像緩存。 91 resp.setHeader("Pragma", "no-cache"); 92 resp.setHeader("Cache-Control", "no-cache"); 93 resp.setDateHeader("Expires", 0); 94 95 resp.setContentType("image/jpeg"); 96 97 // 將圖像輸出到Servlet輸出流中。 98 ServletOutputStream sos = resp.getOutputStream(); 99 ImageIO.write(buffImg, "jpeg", sos); 100 sos.close(); 101 102 return null; 103 } 104 105 // 得到隨機字符 106 private String randomStr(int n) { 107 String str1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; 108 String str2 = ""; 109 int len = str1.length() - 1; 110 double r; 111 for (int i = 0; i < n; i++) { 112 r = (Math.random()) * len; 113 str2 = str2 + str1.charAt((int) r); 114 } 115 return str2; 116 } 117 118 // 得到隨機顏色 119 private Color getRandColor(int fc, int bc) {// 給定范圍獲得隨機顏色 120 if (fc > 255) 121 fc = 255; 122 if (bc > 255) 123 bc = 255; 124 int r = fc + random.nextInt(bc - fc); 125 int g = fc + random.nextInt(bc - fc); 126 int b = fc + random.nextInt(bc - fc); 127 return new Color(r, g, b); 128 } 129 130 // /** 131 // * 產生隨機字體 132 // */ 133 // private Font getFont(int size) { 134 // Font font[] = new Font[5]; 135 // font[0] = new Font("Ravie", Font.PLAIN, size); 136 // font[1] = new Font("Antique Olive Compact", Font.PLAIN, size); 137 // font[2] = new Font("Fixedsys", Font.PLAIN, size); 138 // font[3] = new Font("Wide Latin", Font.PLAIN, size); 139 // font[4] = new Font("Gill Sans Ultra Bold", Font.PLAIN, size); 140 // return font[random.nextInt(5)]; 141 // } 142 143 // 扭曲方法 144 private void shear(Graphics g, int w1, int h1, Color color) { 145 shearX(g, w1, h1, color); 146 shearY(g, w1, h1, color); 147 } 148 149 private void shearX(Graphics g, int w1, int h1, Color color) { 150 151 int period = random.nextInt(2); 152 153 boolean borderGap = true; 154 int frames = 1; 155 int phase = random.nextInt(2); 156 157 for (int i = 0; i < h1; i++) { 158 double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); 159 g.copyArea(0, i, w1, 1, (int) d, 0); 160 if (borderGap) { 161 g.setColor(color); 162 g.drawLine((int) d, i, 0, i); 163 g.drawLine((int) d + w1, i, w1, i); 164 } 165 } 166 167 } 168 169 private void shearY(Graphics g, int w1, int h1, Color color) { 170 171 int period = random.nextInt(40) + 10; // 50; 172 173 boolean borderGap = true; 174 int frames = 20; 175 int phase = 7; 176 for (int i = 0; i < w1; i++) { 177 double d = (double) (period >> 1) * Math.sin((double) i / (double) period + (6.2831853071795862D * (double) phase) / (double) frames); 178 g.copyArea(i, 0, 1, h1, 0, (int) d); 179 if (borderGap) { 180 g.setColor(color); 181 g.drawLine(i, (int) d, i, 0); 182 g.drawLine(i, (int) d + h1, i, h1); 183 } 184 185 } 186 187 } 188 189 public BufferedImage getBuffImg() { 190 return buffImg; 191 } 192 @Override 193 public String list() throws Exception { 194 return null; 195 } 196 197 @Override 198 public String create() throws Exception { 199 return null; 200 } 201 202 @Override 203 public String update() throws Exception { 204 return null; 205 } 206 207 @Override 208 public String delete() throws Exception { 209 return null; 210 } 211 212 @Override 213 public String listByPage() throws Exception { 214 return null; 215 } 216 217 public boolean isSuccess() { 218 return success; 219 } 220 221 public void setSuccess(boolean success) { 222 this.success = success; 223 } 224 225 public String getMessage() { 226 return message; 227 } 228 229 public void setMessage(String message) { 230 this.message = message; 231 } 232 233 }
效果: