这里我使用的View层是SpringMvc,之所以没有因为Struts2,是因为SpringMvc更为方便一点,SpringMvc确实是一个非常之方便的前端框架,但是我不是太喜欢用,就像一个东西你用习惯了之后很难去改变一样。如果叫你不用ecplise去开发,你说你会不会哭一样。但是新技术更新不止,逼着我们硬着头皮去学。这也是没有办法的事情
上篇写了之后,隔了这么长的时间去写是因为我上个星期比较忙,加上通宵上线了一夜,好几天都没有恢复过来 。好了废话不多说了,看下代码
首先看下web.xml
<span style="font-size:14px;"><?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>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>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
</span>
注意这里的dispatcher如果名字是这个,且没有初始化的话,SpringMvc框架会默认去读/WEB-INF/dispatcher-servlet.xml
也可以自己去初始化
<span style="font-size:14px;"> <servlet>
<span style="white-space:pre"> </span><servlet-name>dispatcher</servlet-name>
<span style="white-space:pre"> </span><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span><init-param>
<span style="white-space:pre"> </span><param-name>contextConfigLocation</param-name>
<span style="white-space:pre"> </span><param-value>/WEB-INF/conf/*-servlet.xml</param-value>
<span style="white-space:pre"> </span></init-param>
<span style="white-space:pre"> </span><load-on-startup>1</load-on-startup>
<span style="white-space:pre"> </span></servlet>
<span style="white-space:pre"> </span><servlet-mapping>
<span style="white-space:pre"> </span><servlet-name>dispatcher</servlet-name>
<span style="white-space:pre"> </span><url-pattern>/</url-pattern>
<span style="white-space:pre"> </span></servlet-mapping></span>
它会读到/WEB-INF/config/*-servlet.xml文件
我们来看下dispatcher-servlet.xml
<span style="font-size:14px;"><?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="com.tgb.web.controller"/>
<context:component-scan base-package="com.huawei.action"/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 设置multipartResolver才能完成文件上传 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="5000000" />
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="com.tgb.web.controller.UserException">error</prop>
<prop key="java.lang.NullPointException">exception</prop>
</props>
</property>
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="/WEB-INF/conf/ehcache.xml"/>
</bean>
<bean id="demoCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"/>
<property name="cacheName" value="demoCache"/>
</bean>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/person/*"/><!-- 如果不配置或/*,将拦截所有的controller -->
<bean class="com.huawei.interceptor.OrgMgtInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
</beans>
</span>
<context:component-scan base-package="com.tgb.web.controller"/>
在xml配置了这个标签后,spring可以自动去扫描base-pack下面或者子包下面的java文件,如果扫描到有@Component @Controller@Service等这些注解的类,则把这些类注册为bean注意:如果配置了<context:component-scan>那么<context:annotation-config/>标签就可以不用再xml中配置了,因为前者包含了后者
<mvc:annotation-driven/>这个springmvc的组件,这里就不细说了,因为说了感觉没有太大的意义,把这个说清了,我这篇Ehcache就不用写下去了,因为去搞SpringMvc去了,就是可以使用注入,方便操作在spring3.0以后才有的
重点看下这个
<span style="font-size:14px;"><bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="/WEB-INF/conf/ehcache.xml"/>
</bean>
<bean id="demoCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager" ref="cacheManager"/>
<property name="cacheName" value="demoCache"/>
</bean>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/person/*"/><!-- 如果不配置或/*,将拦截所有的controller -->
<bean class="com.huawei.interceptor.OrgMgtInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors> </span>
看下EhCacheManagerFactroyBean的SpringApi
我们把所有的配置文件都放到/WEB-INF/conf下。这样方便管理
在看下EhCacheFactoryBean,我们首先把EhCacheManagerFactroyBean,然后设置下cacheName设置为我们自己设定的名字,下面是ehcache.xml配置文件
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
maxElementsOnDisk="0"
eternal="true"
overflowToDisk="true"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
diskSpoolBufferSizeMB="50"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LFU"
/>
<cache name="demoCache"
maxElementsInMemory="100"
maxElementsOnDisk="0"
eternal="true"
overflowToDisk="true"
diskPersistent="false"
timeToIdleSeconds="119"
timeToLiveSeconds="119"
diskSpoolBufferSizeMB="50"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LFU"
/>
<!--
name:Cache的名称,必须是唯一的(ehcache会把这个cache放到hashmap里)
maxElementsInMemory:内存中保持的对象数量
maxElementsOnDisk:DiskStore中保持的对象数量,默认为0,表示不限制
eternal:是否是永恒的数据,如果是,则它的超过设置会被忽略
overflowToDisk:如果内存中数量超过maxElementsInMermory限制,是否要缓存到磁盘上
diskPersistent:是否在磁盘上持久化。指重启jvm后,数据是否有效,默认为false
timeToIdleSeconds:对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false时有效,默认为0,表示一直可以访问
timeToLiveSeconds:对象存活时间,指对象从创建到失效所需要的时间,只对eternal为false时有效,默认值为0,表示一直可以访问
diskSpoolBufferSizeMB:DiskStore使用的磁盘大小,默认值为30m。每个cache使用各自的DiskStore
memoryStoreEvictionPolicy:如果内存中数据超过内存限制,向磁盘缓存时的策略。默认值为LRU,可选 FIFO,LFU
-->
</ehcache>
上面关于一些字段的定义我也写得很清楚了
下面是
<span style="font-size:14px;"><mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/person/*"/><!-- 如果不配置或/*,将拦截所有的controller -->
<bean class="com.huawei.interceptor.OrgMgtInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors> </span>
上面也写得比较清楚了,这些写的目的是为了拦截URL /person/*下的所有controller
要记得清楚这里是先写OrgMgtInterceptor之后才进/person/*下的方法,所以以登录页面来说,初始化页面肯定不能去拦截,我在写的时候就写错了,所以在方法里补救了下
来看下OrgMgtInterceptor
package com.huawei.interceptor;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.net.InetAddress;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.huawei.dao.Person;
public class OrgMgtInterceptor implements HandlerInterceptor{
@Resource(name="demoCache")
private Cache cache;
public Cache getCache() {
return cache;
}
public void setCache(Cache cache) {
this.cache = cache;
}
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
//执行顺序:3、afterCompletion
}
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
//执行顺序: 2、
}
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object arg2) throws Exception {
String url = request.getRequestURL().toString();
url = url.substring(url.lastIndexOf("/")+1, url.length());
if("login".equals(url)||"login1".equals(url)||"main2".equals(url)){
return true;
}
Person person = (Person) request.getSession().getAttribute("name");
if("boss".equals(person.getName())&&"123456".equals(person.getPassword()))
{
response.sendRedirect(request.getContextPath() + "/person/main2");
return false;
}
else
{
Element elementPerson = cache.get(person.getName());
if(elementPerson!=null)
{
if(person.getPassword().equals(((Person) elementPerson.getValue()).getPassword()))
{
return true;
}
response.sendRedirect(request.getContextPath() + "/person/login");
return false;
}
else
{
response.sendRedirect(request.getContextPath() + "/person/login");
return false;
}
}
}
}
这里我们首先要继承HandlerInterceptor
其次我们要实现的是
public boolean preHandle这个方法就行了
我写这个的目的是个简单的应用,就是登录之后我把用户存放在ehcache中,如果是boss用户的话先验证,然后去到main2 Action中
如果是普通的用户,会先在ehcache中校验用户名和密码是否正确,然后去到main1 Action中。
package com.huawei.action;
import java.io.Serializable;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.huawei.dao.Person;
import com.huawei.interceptor.OrgMgtInterceptor;
@Controller
@RequestMapping("/person")
public class PersonLoginAction {
<span style="white-space:pre"> </span>@Resource(name="demoCache")
<span style="white-space:pre"> </span>private Cache cache;
<span style="white-space:pre"> </span>public Cache getCache()
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>return cache;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>public void setCache(Cache cache)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>this.cache = cache;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>@RequestMapping(value="/login",method=RequestMethod.GET)
<span style="white-space:pre"> </span>public String login()
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>Person person = new Person();
<span style="white-space:pre"> </span>person.setName("chenzj");
<span style="white-space:pre"> </span>person.setPassword("123456");
<span style="white-space:pre"> </span>Person person1 = new Person();
<span style="white-space:pre"> </span>person1.setName("zhaoshuo");
<span style="white-space:pre"> </span>person1.setPassword("123456");
<span style="white-space:pre"> </span>Person person2 = new Person();
<span style="white-space:pre"> </span>person2.setName("zhengdaheng");
<span style="white-space:pre"> </span>person2.setPassword("123456");
<span style="white-space:pre"> </span>Element elementPerson = new Element(person.getName(),person);
<span style="white-space:pre"> </span>cache.put(elementPerson);
<span style="white-space:pre"> </span>elementPerson = new Element(person1.getName(),person1);
<span style="white-space:pre"> </span>cache.put(elementPerson);
<span style="white-space:pre"> </span>elementPerson = new Element(person2.getName(),person2);
<span style="white-space:pre"> </span>cache.put(elementPerson);
<span style="white-space:pre"> </span>return "person/login";
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>@RequestMapping(value="/login1",method=RequestMethod.POST)
<span style="white-space:pre"> </span>public String login(String name,String password,HttpSession session){
<span style="white-space:pre"> </span>Person person = new Person();
<span style="white-space:pre"> </span>person.setName(name);
<span style="white-space:pre"> </span>person.setPassword(password);
<span style="white-space:pre"> </span>session.setAttribute("name", person);
<span style="white-space:pre"> </span>return "redirect:/person/main1";
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>@RequestMapping(value="/main1",method=RequestMethod.GET)
<span style="white-space:pre"> </span>public String login1(){
<span style="white-space:pre"> </span>return "person/main1";
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>@RequestMapping(value="/main2",method=RequestMethod.GET)
<span style="white-space:pre"> </span>public String login2(){
<span style="white-space:pre"> </span>return "person/main2";
<span style="white-space:pre"> </span>}
}<span style="font-family: Arial;"></span>
在去login的时候我先手动把用户塞到ehcache中,这是测试随便写写,怎么方便怎么写嘛
看到login,login1,main2是不拦截的,这也是我设计的不好,但是本人比较懒,所以就懒得改了
login1提交时读取name和password放到session中
在往main1重定向时会进到interceptor中,关于重定向和转发的根本,会在下一篇中讲到
这时候可以去看看OrgMgtInterceptor中写得非常清楚。这里也就不多说了