二、项目搭建步骤:
步骤1.首先创建web工程,在WebContent目录下建立pages目录,在pages目录里创建login.jsp文件,其文件内容如下:
[html] view plain copy <pre name="code" class="html"><%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery/jquery-1.8.0.min.js"></script> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Insert title here</title> </head> <body> <div><font color="red" size="10px">${user.gender}</font></div> <form action="${pageContext.request.contextPath }/loginController/login" method="post" name="loginForm" id="loginForm"> <table style="text-align: right;"> <tr> <td>用户名:</td> <td><input class="username" type="text" id="username" name="username" value=''/></td> </tr> <tr> <td>密码:</td> <td><input class="password" type="password" id="password" name="password" value=""/></td> </tr> </table> <div><input type="button" value="提 交" onclick="login();" /></div> </form> <span style="white-space:pre"> </span><script type="text/javascript"> function login(){ var username = $("#username").val(); var password = $("#password").val(); $("#loginForm").submit(); } [html] view plain copy document.onkeydown=function(event){ e = event ? event :(window.event ? window.event : null); if(e.keyCode==13){ login(); } } </script> </body> </html>
步骤2.配置web.xml文件,文件内容:
[html] view plain copy <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>SpringMVC-Mybatis-Memcached</display-name> <!-- 引入 spring --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:/applicationContext*.xml</param-value> </context-param> <!-- 引入 springMVC --> <servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:/spring-mvc-config.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 编码 UTF-8 --> <filter> <filter-name>SpringMVC-Memcached-Encoding</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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>SpringMVC-Memcached-Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
步骤3.创建spring-mvc-config.xml文件,配置内容:
[html] view plain copy <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd"> <!-- 使用@Controllers前配置 --> <mvc:annotation-driven /> <!-- 容器加载时 自动扫描所有注解 --> <context:component-scan base-package="com.test" /> <!-- 配置静态资源 --> <mvc:resources mapping="/js/**" location="/js/" /> <mvc:resources mapping="/image/**" location="/image/" /> <mvc:resources mapping="/css/**" location="/css/" /> <!-- 使用jsp作为视图 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass"> <value>org.springframework.web.servlet.view.JstlView</value> </property> <!-- 目标路径返回到pages下 使用jsp作为视图 --> <property name="prefix" value="/pages/"></property> <property name="suffix" value=".jsp"></property> </bean> <!-- 异常处理 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="org.apache.shiro.authz.UnauthorizedException">error/403</prop> </props> </property> </bean> </beans>
步骤4.创建jdbc.properties文件,添加内容:
[java] view plain copy jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc\:mysql\://localhost\:3306/demo?user\=root&password\=root
步骤5.创建User对象:
[java] view plain copy package com.test.bean; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = -985141821084238350L; private int id; private String name; private String gender; public User() { } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } }
步骤6.建立IUserDao接口:
[java] view plain copy <pre name="code" class="java">package com.test.dao; import com.test.bean.User; public interface IUserDao { public User getUser(String name); }
步骤7.创建IUserDao.xml文件,配置内容:
[html] view plain copy <pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd"> <!-- 务必配置正确namespace就是所映射的接口类--> <mapper namespace="com.test.dao.IUserDao"> <!-- resultType="User"这个使用的是配置文件里面的别名(配置文件为mybatis-config.xml) --> <select id="getUser" parameterType="string" resultType="User"> select * from user where name=#{name} </select> </mapper>
步骤9.创建MemcachedUtils工具类
[java] view plain copy <pre name="code" class="java">package com.test.utils; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.log4j.Logger; import com.danga.MemCached.MemCachedClient; public class MemcachedUtils { private static final Logger logger = Logger.getLogger(MemcachedUtils.class); private static MemCachedClient cachedClient; static { if (cachedClient == null) cachedClient = new MemCachedClient("memcachedPool"); } private MemcachedUtils() { } /** * 向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。 * * @param key * 键 * @param value * 值 * @return */ public static boolean set(String key, Object value) { return setExp(key, value, null); } /** * 向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。 * * @param key * 键 * @param value * 值 * @param expire * 过期时间 New Date(1000*10):十秒后过期 * @return */ public static boolean set(String key, Object value, Date expire) { return setExp(key, value, expire); } /** * 向缓存添加新的键值对。如果键已经存在,则之前的值将被替换。 * * @param key * 键 * @param value * 值 * @param expire * 过期时间 New Date(1000*10):十秒后过期 * @return */ private static boolean setExp(String key, Object value, Date expire) { boolean flag = false; try { flag = cachedClient.set(key, value, expire); } catch (Exception e) { // 记录Memcached日志 MemcachedLog.writeLog("Memcached set方法报错,key值:" + key + "\r\n" + exceptionWrite(e)); } return flag; } /** * 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对。 * * @param key * 键 * @param value * 值 * @return */ public static boolean add(String key, Object value) { return addExp(key, value, null); } /** * 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对。 * * @param key * 键 * @param value * 值 * @param expire * 过期时间 New Date(1000*10):十秒后过期 * @return */ public static boolean add(String key, Object value, Date expire) { return addExp(key, value, expire); } /** * 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对。 * * @param key * 键 * @param value * 值 * @param expire * 过期时间 New Date(1000*10):十秒后过期 * @return */ private static boolean addExp(String key, Object value, Date expire) { boolean flag = false; try { flag = cachedClient.add(key, value, expire); } catch (Exception e) { // 记录Memcached日志 MemcachedLog.writeLog("Memcached add方法报错,key值:" + key + "\r\n" + exceptionWrite(e)); } return flag; } /** * 仅当键已经存在时,replace 命令才会替换缓存中的键。 * * @param key * 键 * @param value * 值 * @return */ public static boolean replace(String key, Object value) { return replaceExp(key, value, null); } /** * 仅当键已经存在时,replace 命令才会替换缓存中的键。 * * @param key * 键 * @param value * 值 * @param expire * 过期时间 New Date(1000*10):十秒后过期 * @return */ public static boolean replace(String key, Object value, Date expire) { return replaceExp(key, value, expire); } /** * 仅当键已经存在时,replace 命令才会替换缓存中的键。 * * @param key * 键 * @param value * 值 * @param expire * 过期时间 New Date(1000*10):十秒后过期 * @return */ private static boolean replaceExp(String key, Object value, Date expire) { boolean flag = false; try { flag = cachedClient.replace(key, value, expire); } catch (Exception e) { MemcachedLog.writeLog("Memcached replace方法报错,key值:" + key + "\r\n" + exceptionWrite(e)); } return flag; } /** * get 命令用于检索与之前添加的键值对相关的值。 * * @param key * 键 * @return */ public static Object get(String key) { Object obj = null; try { obj = cachedClient.get(key); } catch (Exception e) { MemcachedLog.writeLog("Memcached get方法报错,key值:" + key + "\r\n" + exceptionWrite(e)); } return obj; } /** * 删除 memcached 中的任何现有值。 * * @param key * 键 * @return */ public static boolean delete(String key) { return deleteExp(key, null); } /** * 删除 memcached 中的任何现有值。 * * @param key * 键 * @param expire * 过期时间 New Date(1000*10):十秒后过期 * @return */ public static boolean delete(String key, Date expire) { return deleteExp(key, expire); } /** * 删除 memcached 中的任何现有值。 * * @param key * 键 * @param expire * 过期时间 New Date(1000*10):十秒后过期 * @return */ private static boolean deleteExp(String key, Date expire) { boolean flag = false; try { flag = cachedClient.delete(key, expire); } catch (Exception e) { MemcachedLog.writeLog("Memcached delete方法报错,key值:" + key + "\r\n" + exceptionWrite(e)); } return flag; } /** * 清理缓存中的所有键/值对 * * @return */ public static boolean flashAll() { boolean flag = false; try { flag = cachedClient.flushAll(); } catch (Exception e) { MemcachedLog.writeLog("Memcached flashAll方法报错\r\n" + exceptionWrite(e)); } return flag; } /** * 返回异常栈信息,String类型 * * @param e * @return */ private static String exceptionWrite(Exception e) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); pw.flush(); return sw.toString(); } /** * * @ClassName: MemcachedLog * @Description: Memcached日志记录 * */ private static class MemcachedLog { private final static String MEMCACHED_LOG = "D:\\memcached.log"; private final static String LINUX_MEMCACHED_LOG = "/usr/local/logs/memcached.log"; private static FileWriter fileWriter; private static BufferedWriter logWrite; // 获取PID,可以找到对应的JVM进程 private final static RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); private final static String PID = runtime.getName(); /** * 初始化写入流 */ static { try { String osName = System.getProperty("os.name"); if (osName.indexOf("Windows") == -1) { fileWriter = new FileWriter(MEMCACHED_LOG, true); } else { fileWriter = new FileWriter(LINUX_MEMCACHED_LOG, true); } logWrite = new BufferedWriter(fileWriter); } catch (IOException e) { logger.error("memcached 日志初始化失败", e); closeLogStream(); } } /** * 写入日志信息 * * @param content * 日志内容 */ public static void writeLog(String content) { try { logWrite.write("[" + PID + "] " + "- [" + new SimpleDateFormat("yyyy年-MM月-dd日 hh时:mm分:ss秒").format(new Date().getTime()) + "]\r\n" + content); logWrite.newLine(); logWrite.flush(); } catch (IOException e) { logger.error("memcached 写入日志信息失败", e); } } /** * 关闭流 */ private static void closeLogStream() { try { fileWriter.close(); logWrite.close(); } catch (IOException e) { logger.error("memcached 日志对象关闭失败", e); } } } }
步骤10.创建IUserServer接口:
[java] view plain copy <pre name="code" class="java">package com.test.server; import com.test.bean.User; public interface IUserServer { public User testMethod(String userName); }
步骤11.创建UserServerImpl.Java类实现IUserServer接口:
[java] view plain copy <pre name="code" class="java">package com.test.server; import net.spy.memcached.MemcachedClient; import org.springframework.beans.factory.annotation.Autowired; import com.test.bean.User; import com.test.dao.IUserDao; public class UserServerImpl implements IUserServer { private IUserDao userDao; private MemcachedClient memcachedClient; public User testMethod(String userName) { User user; // 判断缓存中数据是否存在,如果不存在则添加,存在则读取 if (this.memcachedClient.get("user") != null) { user = (User) this.memcachedClient.get("user"); System.out.println("本次操作是在缓存中查询数据..."); } else { user = userDao.getUser(userName); this.memcachedClient.add("user", 100, user); System.out.println("本次操作是在数据库中查询数据..."); } return user; } public IUserDao getUserDao() { return userDao; } // 依赖注入,根据属性名自动注入 @Autowired public void setUserDao(IUserDao userDao) { this.userDao = userDao; } public MemcachedClient getMemcachedClient() { return memcachedClient; } // 依赖注入(分布式缓存,在spring中自动生成) @Autowired public void setMemcachedClient(MemcachedClient memcachedClient) { this.memcachedClient = memcachedClient; } }
步骤12.创建LoginController:
[java] view plain copy <pre name="code" class="java">package com.test.web; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.test.bean.User; import com.test.server.IUserServer; @Controller @RequestMapping("/loginController") public class LoginController { IUserServer server; // 根据访问连接调用控制器,此控制器的调用连接为localhost:8080/SpringMVC-Mybatis-Memcached/loginController/login @RequestMapping("login") public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { // 创建ModelAndView对象,login为返回的jsp页面的名称,全路径是根据在springMVC配置文件中配置的前缀与后缀拼接而成 ModelAndView mode = new ModelAndView("login"); User user = server.testMethod("aa"); // 将对象加入mode返回到前台页面 mode.addObject("user", user); return mode; } public IUserServer getServer() { return server; } // 依赖注入,根据属性名自动注入 @Autowired public void setServer(IUserServer server) { this.server = server; } }
步骤13.创建spring-memcached.xml文件,添加内容:
[html] view plain copy <pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> <!--memcached注入 --> <bean id="memcachedClient" class="net.spy.memcached.spring.MemcachedClientFactoryBean"> <property name="servers" value="127.0.0.1:11211" /> <property name="protocol" value="BINARY" /> <property name="transcoder"> <bean class="net.spy.memcached.transcoders.SerializingTranscoder"> <property name="compressionThreshold" value="1024" /> </bean> </property> <property name="opTimeout" value="50" /> <property name="timeoutExceptionThreshold" value="1998" /> <property name="hashAlg"> <value type="net.spy.memcached.DefaultHashAlgorithm">KETAMA_HASH</value> </property> <property name="locatorType" value="CONSISTENT" /> <property name="failureMode" value="Redistribute" /> <property name="useNagleAlgorithm" value="false" /> </bean> </beans>
步骤14.创建applicationContext.xml文件,配置其内容:
[html] view plain copy <pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- 获取JDBC连接属性 --> <context:property-placeholder location="classpath:jdbc.properties" /> <!-- 配置数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}"></property> <property name="url" value="${jdbc.url}"> </property> </bean> <!-- sqlSessionFactory --> <!-- MyBatis在spring中Bean的配置,都是固定的 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="configLocation" value="classpath:mybatis-config.xml" /> <property name="dataSource" ref="dataSource" /> </bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory" /> </bean> <!-- 引入memcached配置文件 --> <import resource="spring-memcached.xml"/> <!-- 配置映射器 --> <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.test.dao.IUserDao" /> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean> <!-- 为业务逻辑层注入数据的对象 --> <bean id="userServer" class="com.test.server.UserServerImpl"> <property name="userDao" ref="userMapper"></property> <property name="memcachedClient" ref="memcachedClient"></property> </bean> <bean id="login" class="com.test.web.LoginController"> <property name="server" ref="userServer"></property> </bean> </beans>