二、项目搭建步骤:
步骤1.首先创建web工程,在WebContent目录下建立pages目录,在pages目录里创建login.jsp文件,其文件内容如下:
- <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();
- }
- document.onkeydown=function(event){
- e = event ? event :(window.event ? window.event : null);
- if(e.keyCode==13){
- login();
- }
- }
- </script>
- </body>
- </html>
步骤2.配置web.xml文件,文件内容:
- <?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文件,配置内容:
- <?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文件,添加内容:
- jdbc.driverClassName=com.mysql.jdbc.Driver
- jdbc.url=jdbc\:mysql\://localhost\:3306/demo?user\=root&password\=root
步骤5.创建User对象:
- 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接口:
- <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文件,配置内容:
- <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工具类
- <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接口:
- <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接口:
- <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:
- <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文件,添加内容:
- <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文件,配置其内容:
- <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>