一、在我们实现框架页面之前,我们先来做另外两件工作:
- 日志记录,引入log4j的jar包,创建log4j.properties文件
log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.SimpleLayout log4j.rootCategory=DEBUG, console
- 在web.xml文件中配置Spring的字符过滤器--对用户的请求以及服务器发出的响应的URL的编码进行转换,否则当用户发送的请求包含中文时,比如表单提交时用户名输入为中文,容易出现乱码现象。但是Spring的这个字符过滤器最好配置在其它过滤器之前。
<!-- Spring字符过滤器 --> <filter> <filter-name>CharsetFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharsetFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
二、框架页面实现
- 我们希望用户在访问我们系统时,页面的title总是显示我们系统的名称--手机进销存管理系统,如那么我们可以自定义一个监听器SysInitListener,在系统启动的时候通过读取配置文件,然后将系统名称放到application中,我们就可以通过EL表达式在页面上获取,web.xml配置如下
自定义的监听器SysInitListener的代码非常简单,如下:<context-param> <param-name>sysname</param-name> <param-value> 手机进销存管理系统 </param-value> </context-param> <!-- 自定义的系统初始化监听器 --> <listener> <listener-class>com.mobile.utils.SysInitListener</listener-class> </listener>
public class SysInitListener implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent arg0) { // TODO Auto-generated method stub } @Override public void contextInitialized(ServletContextEvent event) { ServletContext application = event.getServletContext(); String sysname = application.getInitParameter("sysname"); application.setAttribute("sysname", sysname); } }
- 系统登录验证码生成类--ValidateCodeGenerator.java
创建一个Servlet,用于当用户请求系统时,调用ValidateCodeGenerator生成验证码,并将验证码存放到Session中,以便在页面获取;另外当用户想更换验证码时,可以点击验证码图片跟换另一个验证码,使用AJAX请求,但是之前我们将验证码放到Session中,如果不是一个新的请求,会直接从Session中获取,那么就无法实现验证码图片的更换,所以我们在每个请求加上一个时间,可以当用户想更换图片时,服务器就会认为是一个新的请求,从而实现验证码的更换。public class ValidateCodeGenerator { //用于生成验证码的字符数组 final private char[] chars = "2345678ABCDEFGHJKLMPQRSTUVWXYabcdefhkmnqrstuvwx" .toCharArray(); //验证码的字符字体 private static String[] fontNames = new String[] { "Courier", "Arial", "Verdana", "Georgia", "Times", "Tahoma" }; //字符样式 private static int[] fontStyle = new int[] { Font.PLAIN, Font.BOLD, Font.ITALIC, Font.BOLD | Font.ITALIC }; private int width = 160; //验证码图片宽度 private int height = 60; //验证码图片高度 private int charCnt = 4; //验证码图片字符数 private int disturbLineNum = 10; //干扰线条数 private OutputStream os; public ValidateCodeGenerator(OutputStream os) { this.os = os; } public ValidateCodeGenerator(OutputStream os, int width, int height, int charCnt) { this.width = width; this.height = height; this.charCnt = charCnt; this.os = os; } /** * 画验证码图片 * @return * @throws IOException */ public String drawCode() throws IOException { //验证码图片 BufferedImage bi = new BufferedImage(this.width, this.height, BufferedImage.TYPE_INT_RGB); //图片画笔 Graphics2D g = bi.createGraphics(); //用画笔设置不骗颜色 g.setColor(new Color(245, 245, 245)); g.fillRect(0, 0, this.width, this.height); //画干扰线 drawDisturbLine(g); //在验证码大图片的基础上生成四个小的图片,用于存放生成的单个验证码字符 BufferedImage[] bis = new BufferedImage[charCnt]; //生成字符 char[] codes = generateCode(); for (int i = 0; i < charCnt; i++) { bis[i] = generateBuffImg(codes[i]); g.drawImage(bis[i], null, (int) (this.height * 0.62) * i, 0); } g.dispose(); ImageIO.write(bi, "gif", os); return new String(codes); } /** * 将生成的每个字符放到图片上,也就是在我们整个验证码大图片上,生成的验证码字符其实是四个小图片 * @param c * @return */ private BufferedImage generateBuffImg(char c) { String tmp = Character.toString(c); Color forecolor = getRandomColor(); Color backcolor = new Color(255, 255, 255, 0); String fontName = getRandomFontName(); int fontStyle = getRandomStyle(); int fontSize = getRandomSize(); int strX = (this.height - fontSize) / 2; int strY = (this.height - fontSize) / 2 + fontSize; //设置字符旋转的角度 double arch = getRandomArch(); BufferedImage ret = new BufferedImage(this.height, this.height, BufferedImage.TYPE_INT_ARGB); Graphics2D g = ret.createGraphics(); g.setColor(backcolor); g.fillRect(0, 0, this.height, this.height); g.setColor(forecolor); g.setFont(new Font(fontName, fontStyle, fontSize)); g.rotate(arch, this.height / 2, this.height / 2); //在生成的小图片上画生成字符串,其实就是我们生成的单个字符 g.drawString(tmp, strX, strY); g.dispose(); return ret; } private double getRandomArch() { return ((int) (Math.random() * 1000) % 2 == 0 ? -1 : 1) * Math.random(); } private Color getRandomColor() { int r = (int) (Math.random() * 10000) % 200; int g = (int) (Math.random() * 10000) % 200; int b = (int) (Math.random() * 10000) % 200; return new Color(r, g, b); } private String getRandomFontName() { int pos = (int) (Math.random() * 10000) % (fontNames.length); return fontNames[pos]; } private int getRandomStyle() { int pos = (int) (Math.random() * 10000) % (fontStyle.length); return fontStyle[pos]; } private int getRandomSize() { int max = (int) (this.height * 0.98); int min = (int) (this.height * 0.75); return (int) (Math.random() * 10000) % (max - min + 1) + min; } /** * 生成验证码字符方法 * @return */ private char[] generateCode() { //用于存放生成字符的数组 char[] ret = new char[charCnt]; for (int i = 0; i < charCnt; i++) { int letterPos = (int) (Math.random() * 10000) % (chars.length); ret[i] = chars[letterPos]; } return ret; } /** * 画干扰线 * @param graphics--画笔 */ private void drawDisturbLine(Graphics2D graphics) { for (int i = 0; i < disturbLineNum; i++) { //随机获取干扰线颜色 graphics.setColor(getRandomColor()); int x = (int) (Math.random() * 10000) % (this.width + 1) + 1; int x1 = (int) (Math.random() * 10000) % (this.width + 1) + 1; int y = (int) (Math.random() * 10000) % (this.height + 1) + 1; int y1 = (int) (Math.random() * 10000) % (this.height + 1) + 1; graphics.drawLine(x, y, x1, y1); } } public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("d:/Space/tmp/tmp.gif"); ValidateCodeGenerator vg = new ValidateCodeGenerator(fos); vg.drawCode(); } }