Top

JAVA Spring MyBatis DAY05

  1. 中文乱码解决方案
  2. 异常处理
  3. 处理NETCTOSS项目中的异常
  4. 资费列表
  5. 拦截器案例
  6. 登录检查

1 中文乱码解决方案

1.1 问题

解决NETCTOSS登录时,输入中文的乱码问题。

1.2 方案

使用Spring提供的filter,指定编码为UTF-8。

1.3 步骤

步骤一:问题演示

打开NETCTOSS1登录页面,输入中文账号并点击登录,浏览器显示效果如下图:

图-1

步骤二:配置filter

在web.xml中配置filter,指定编码为UTF-8,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="/java.sun.com/xml/ns/javaee" 
	xmlns:xsi="/www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="/java.sun.com/xml/ns/javaee 
	/java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

	<servlet>
		<servlet-name>spring</servlet-name>
		<servlet-class>
			org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:applicationContext.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>spring</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
	
	<filter>
	<filter-name>encodingFilter</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>encodingFilter</filter-name>
	<url-pattern>/*</url-pattern>
	</filter-mapping>	

</web-app>

步骤三:测试

重新部署并启动项目,再次打开登录页面,输入中文账号登录,浏览器显示效果如下图:

图-2

1.4 完整代码

web.xml完整代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="/java.sun.com/xml/ns/javaee" 
	xmlns:xsi="/www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="/java.sun.com/xml/ns/javaee 
	/java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

	<servlet>
		<servlet-name>spring</servlet-name>
		<servlet-class>
			org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:applicationContext.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>spring</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
	
	<filter>
	<filter-name>encodingFilter</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>encodingFilter</filter-name>
	<url-pattern>/*</url-pattern>
	</filter-mapping>	

</web-app>

2 异常处理

2.1 问题

使用Spring MVC处理项目中发生的异常。

2.2 方案

Spring MVC处理异常有3种方式:

  1. 使用Spring MVC预置的类SimpleMappingExceptionResolver处理异常。
  2. 实现异常处理接口HandlerExceptionResolver来自定义异常处理类。
  3. 使用@ExceptionHandler处理异常。

本案例将演示第1、3种异常处理的方式,第2种方式可以由第1种方式代替,故省略。

2.3 步骤

步骤一:开发准备

创建项目Spring05,导入jar包,如下图:

图-3

配置web.xml,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="/java.sun.com/xml/ns/javaee" 
	xmlns:xsi="/www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="/java.sun.com/xml/ns/javaee 
	/java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

	<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.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>

</web-app>

配置spring-mvc.xml,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="/www.springframework.org/schema/beans" 
	xmlns:xsi="/www.w3.org/2001/XMLSchema-instance"
	xmlns:context="/www.springframework.org/schema/context" 
	xmlns:jdbc="/www.springframework.org/schema/jdbc"  
	xmlns:jee="/www.springframework.org/schema/jee" 
	xmlns:tx="/www.springframework.org/schema/tx"
	xmlns:aop="/www.springframework.org/schema/aop" 
	xmlns:mvc="/www.springframework.org/schema/mvc"
	xmlns:util="/www.springframework.org/schema/util"
	xmlns:jpa="/www.springframework.org/schema/data/jpa"
	xsi:schemaLocation="
		/www.springframework.org/schema/beans /www.springframework.org/schema/beans/spring-beans-3.2.xsd
		/www.springframework.org/schema/context /www.springframework.org/schema/context/spring-context-3.2.xsd
		/www.springframework.org/schema/jdbc /www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
		/www.springframework.org/schema/jee /www.springframework.org/schema/jee/spring-jee-3.2.xsd
		/www.springframework.org/schema/tx /www.springframework.org/schema/tx/spring-tx-3.2.xsd
		/www.springframework.org/schema/data/jpa /www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		/www.springframework.org/schema/aop /www.springframework.org/schema/aop/spring-aop-3.2.xsd
		/www.springframework.org/schema/mvc /www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		/www.springframework.org/schema/util /www.springframework.org/schema/util/spring-util-3.2.xsd">
	
	<!--开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>
	
	<!--开启MVC注解扫描 -->
	<mvc:annotation-driven/>
	
	<!--定义视图解析器ViewResolver -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/"/>
		<property name="suffix" value=".jsp"/>
	</bean>
	
</beans>

步骤二:使用SimpleMappingExceptionResolver处理异常

在spring-mvc.xml中配置SimpleMappingExceptionResolver,追加代码如下:

	<!--处理系统异常 -->
	<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<property name="exceptionMappings">
	<props>		
	<prop key="java.lang.Exception">jsp/error</prop>
	</props>
	</property>
	</bean>

创建HelloController,代码如下:

package com.tarena.web;

import java.io.Serializable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/demo")
public class HelloController implements Serializable {
		
	@RequestMapping("/hello.do")
	public String hello() {
		System.out.println("hello");
		Integer.valueOf("abc");
		return "jsp/hello";
	}
		
}

在WEB-INF/jsp下创建hello.jsp,代码如下:

<%@page pageEncoding="utf-8"%>
<html>
<head></head>
<body>
	<h1>Hello, SpringMVC.</h1>
</body>
</html>

在WEB-INF/jsp下创建error.jsp,代码如下:

<%@page pageEncoding="utf-8"%>
<html>
<head></head>
<body>
	<h1 style="color:red;">系统报错,请联系管理员.</h1>
</body>
</html>

步骤三:测试

部署项目并启动Tomcat,浏览器访问/localhost:8088/Spring05/demo/hello.do,效果如下图:

图-4

步骤四:使用@ExceptionHandler处理异常

修改HelloController,增加异常处理方法,代码如下:

package com.tarena.web;

import java.io.Serializable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/demo")
public class HelloController implements Serializable {
	
	@ExceptionHandler
	public String handleException(Exception e, 
		HttpServletRequest request, HttpServletResponse response) 
		throws Exception {
		if(e instanceof NumberFormatException) {
			request.setAttribute("message", "亲,请输入数字哦.");
			return "jsp/message";
		} else {
			throw e;
		}
	}
	
	@RequestMapping("/hello.do")
	public String hello() {
		System.out.println("hello");
		Integer.valueOf("abc");
		return "jsp/hello";
	}
	
	@RequestMapping("/hi.do")
	public String hi() {
		System.out.println("hi");
		String name = "abc";
		name.charAt(9);
		return "jsp/hello";
	}


}

在WEB-INF/jsp下创建message.jsp,代码如下:

<%@page pageEncoding="utf-8"%>
<html>
<head></head>
<body>
	<h1>${message }</h1>
</body>
</html>

步骤五:测试

重新部署项目并启动Tomcat,浏览器访问/localhost:8088/Spring05/demo/hello.do,效果如下图:

图-5

浏览器访问/localhost:8088/Spring05/demo/hi.do,效果如下图:

图-6

2.4 完整代码

web.xml完整代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="/java.sun.com/xml/ns/javaee" 
	xmlns:xsi="/www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="/java.sun.com/xml/ns/javaee 
	/java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

	<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.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>

</web-app>

spring-mvc.xml完整代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="/www.springframework.org/schema/beans" 
	xmlns:xsi="/www.w3.org/2001/XMLSchema-instance"
	xmlns:context="/www.springframework.org/schema/context" 
	xmlns:jdbc="/www.springframework.org/schema/jdbc"  
	xmlns:jee="/www.springframework.org/schema/jee" 
	xmlns:tx="/www.springframework.org/schema/tx"
	xmlns:aop="/www.springframework.org/schema/aop" 
	xmlns:mvc="/www.springframework.org/schema/mvc"
	xmlns:util="/www.springframework.org/schema/util"
	xmlns:jpa="/www.springframework.org/schema/data/jpa"
	xsi:schemaLocation="
		/www.springframework.org/schema/beans /www.springframework.org/schema/beans/spring-beans-3.2.xsd
		/www.springframework.org/schema/context /www.springframework.org/schema/context/spring-context-3.2.xsd
		/www.springframework.org/schema/jdbc /www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
		/www.springframework.org/schema/jee /www.springframework.org/schema/jee/spring-jee-3.2.xsd
		/www.springframework.org/schema/tx /www.springframework.org/schema/tx/spring-tx-3.2.xsd
		/www.springframework.org/schema/data/jpa /www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		/www.springframework.org/schema/aop /www.springframework.org/schema/aop/spring-aop-3.2.xsd
		/www.springframework.org/schema/mvc /www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		/www.springframework.org/schema/util /www.springframework.org/schema/util/spring-util-3.2.xsd">
	
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>
	
	<!-- 开启MVC注解扫描 -->
	<mvc:annotation-driven/>
	
	<!-- 定义视图解析器ViewResolver -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/"/>
		<property name="suffix" value=".jsp"/>
	</bean>
	
	<!-- 处理系统异常 -->
	<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<property name="exceptionMappings">
	<props>		
	<prop key="java.lang.Exception">jsp/error</prop>
	</props>
	</property>
	</bean>
	
</beans>

HelloController完整代码如下:

package com.tarena.web;

import java.io.Serializable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/demo")
public class HelloController implements Serializable {
	
	@ExceptionHandler
	public String handleException(Exception e, 
		HttpServletRequest request, HttpServletResponse response) 
		throws Exception {
		if(e instanceof NumberFormatException) {
			request.setAttribute("message", "亲,请输入数字哦.");
			return "jsp/message";
		} else {
			throw e;
		}
	}
	
	@RequestMapping("/hello.do")
	public String hello() {
		System.out.println("hello");
		Integer.valueOf("abc");
		return "jsp/hello";
	}
	
	@RequestMapping("/hi.do")
	public String hi() {
		System.out.println("hi");
		String name = "abc";
		name.charAt(9);
		return "jsp/hello";
	}

}

hello.jsp完整代码如下:

<%@page pageEncoding="utf-8"%>
<html>
<head></head>
<body>
	<h1>Hello, SpringMVC.</h1>
</body>
</html>

error.jsp完整代码如下:

<%@page pageEncoding="utf-8"%>
<html>
<head></head>
<body>
	<h1 style="color:red;">系统报错,请联系管理员.</h1>
</body>
</html>

message.jsp完整代码如下:

<%@page pageEncoding="utf-8"%>
<html>
<head></head>
<body>
	<h1>${message }</h1>
</body>
</html>

3 处理NETCTOSS项目中的异常

3.1 问题

处理NETCTOSS项目中出现的异常。

3.2 方案

  1. 采用@ExceptionHandler统一处理业务异常
  2. 采用SimpleMappingExceptionResolver统一处理系统异常

3.3 步骤

步骤一:使用@ExceptionHandler处理LoginController中的业务异常

修改LoginController,增加异常处理方法,并使用@ExceptionHandler处理业务异常,代码如下:

package com.tarena.web;

import java.io.Serializable;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import com.tarena.entity.Admin;
import com.tarena.exception.AdminCodeException;
import com.tarena.exception.PasswordException;
import com.tarena.service.LoginService;

@Controller
@RequestMapping("/login")
public class LoginController implements Serializable {
	
	@Resource
	private LoginService loginService;
	
	@ExceptionHandler
	public String execute(HttpServletRequest request,
			HttpServletResponse response, Exception e) throws Exception {
		if(e instanceof AdminCodeException
				|| e instanceof PasswordException) {
			//业务异常自己处理
			request.setAttribute("message", e.getMessage());
			request.setAttribute(
				"adminCode", request.getParameter("adminCode"));
			request.setAttribute(
				"password", request.getParameter("password"));
			return "main/login";
		} else {
			//系统异常抛出,交给Spring处理
			throw e;
		}
	}

	@RequestMapping("/toLogin.do")
	public String toLogin() {
		return "main/login";
	}
	
	@RequestMapping("/toIndex.do")
	public String toIndex() {
		return "main/index";
	}
	
	@RequestMapping("/checkLogin.do")
	public String checkLogin(String adminCode, String password, 
			ModelMap model, HttpSession session) {
#cold_bold//		try {
#cold_bold//			Admin admin = 
#cold_bold//				loginService.checkAdminCodeAndPwd(adminCode, password);
#cold_bold//			session.setAttribute("admin", admin);
#cold_bold//		} catch (AdminCodeException e) {
#cold_bold//			model.addAttribute("message", e.getMessage());
#cold_bold//			model.addAttribute("adminCode", adminCode);
#cold_bold//			model.addAttribute("password", password);
#cold_bold//			return "main/login";
#cold_bold//		} catch (PasswordException e) {
#cold_bold//			model.addAttribute("message", e.getMessage());
#cold_bold//			model.addAttribute("adminCode", adminCode);
#cold_bold//			model.addAttribute("password", password);
#cold_bold//			return "main/login";
#cold_bold//		}
#cold_bold		Admin admin = 
#cold_bold			loginService.checkAdminCodeAndPwd(adminCode, password);
#cold_bold		session.setAttribute("admin", admin);		
#cold_bold		return "redirect:toIndex.do";
	}
	
}

步骤二:使用SimpleMappingExceptionResolver处理系统异常

配置applicationContext.xml,增加SimpleMappingExceptionResolver,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="/www.springframework.org/schema/beans" 
	xmlns:xsi="/www.w3.org/2001/XMLSchema-instance"
	xmlns:context="/www.springframework.org/schema/context" 
	xmlns:jdbc="/www.springframework.org/schema/jdbc"  
	xmlns:jee="/www.springframework.org/schema/jee" 
	xmlns:tx="/www.springframework.org/schema/tx"
	xmlns:aop="/www.springframework.org/schema/aop" 
	xmlns:mvc="/www.springframework.org/schema/mvc"
	xmlns:util="/www.springframework.org/schema/util"
	xmlns:jpa="/www.springframework.org/schema/data/jpa"
	xsi:schemaLocation="
		/www.springframework.org/schema/beans /www.springframework.org/schema/beans/spring-beans-3.2.xsd
		/www.springframework.org/schema/context /www.springframework.org/schema/context/spring-context-3.2.xsd
		/www.springframework.org/schema/jdbc /www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
		/www.springframework.org/schema/jee /www.springframework.org/schema/jee/spring-jee-3.2.xsd
		/www.springframework.org/schema/tx /www.springframework.org/schema/tx/spring-tx-3.2.xsd
		/www.springframework.org/schema/data/jpa /www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		/www.springframework.org/schema/aop /www.springframework.org/schema/aop/spring-aop-3.2.xsd
		/www.springframework.org/schema/mvc /www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		/www.springframework.org/schema/util /www.springframework.org/schema/util/spring-util-3.2.xsd">
	
	<util:properties id="jdbc" location="classpath:jdbc.properties"/>
	
	<!--定义数据源 -->
	<bean id="ds" 
		class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="url" value="#{jdbc.url}"/>
		<property name="driverClassName" value="#{jdbc.driver}"/>
		<property name="username" value="#{jdbc.user}"/>
		<property name="password" value="#{jdbc.password}"/>
	</bean>	
	
	<!--开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>
	
	<!--开启MVC注解扫描 -->
	<mvc:annotation-driven/>
	
	<!--定义视图解析器ViewResolver -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/"/>
		<property name="suffix" value=".jsp"/>
	</bean>
	
#cold_bold	<!--处理系统异常-->
#cold_bold	<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
#cold_bold		<property name="exceptionMappings">
#cold_bold	<props>		
#cold_bold	<prop key="java.lang.Exception">main/error</prop>
#cold_bold	</props>
#cold_bold	</property>
#cold_bold	</bean>	
	
</beans>

在WEB-INF/main下,创建系统错误页面error.jsp,代码如下:

<%@page pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "/www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="/www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title> -NetCTOSS</title>
<link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" />
<link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" />
<script language="javascript" type="text/javascript">
var timer;
            //启动跳转的定时器
function startTimes() {
timer = window.setInterval(showSecondes,1000);
            }

var i = 5;
function showSecondes() {
if (i > 0) {
i--;
document.getElementById("secondes").innerHTML = i;
                }
else {
window.clearInterval(timer);
                    //location.href = "login.html";
history.back();
                }
            }

            //取消跳转
function resetTimer() {
if (timer != null && timer != undefined) {
window.clearInterval(timer);
                    //location.href = "login.html";
history.back();
                }
            }
</script>
</head>
<body class="error_page" onload="startTimes();">
<h1 id="error">
	遇到错误,&nbsp;<span id="secondes">5</span>&nbsp;秒后将自动跳转,立即跳转请点击&nbsp;
<a  href="javascript:resetTimer();">返回</a>
</h1>
</body>
</html>

步骤三:测试

打开登录页面,输入错误的账号或密码,点击登录,效果如下图:

图-7

在LoginController中的checkLogin方法中模拟一个系统级错误,比如:

	@RequestMapping("/checkLogin.do")
	public String checkLogin(String adminCode, String password, 
			ModelMap model, HttpSession session) {
//		try {
//			Admin admin = 
//				loginService.checkAdminCodeAndPwd(adminCode, password);
//			session.setAttribute("admin", admin);
//		} catch (AdminCodeException e) {
//			model.addAttribute("message", e.getMessage());
//			model.addAttribute("adminCode", adminCode);
//			model.addAttribute("password", password);
//			return "main/login";
//		} catch (PasswordException e) {
//			model.addAttribute("message", e.getMessage());
//			model.addAttribute("adminCode", adminCode);
//			model.addAttribute("password", password);
//			return "main/login";
//		}
#cold_bold		Integer.valueOf("abc");
		Admin admin = 
			loginService.checkAdminCodeAndPwd(adminCode, password);
		session.setAttribute("admin", admin);		
		return "redirect:toIndex.do";
	}

重新部署项目并启动Tomcat,再次登录,浏览器显示效果如下图:

图-8

3.4 完整代码

LoginController完整代码如下:

package com.tarena.web;

import java.io.Serializable;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import com.tarena.entity.Admin;
import com.tarena.exception.AdminCodeException;
import com.tarena.exception.PasswordException;
import com.tarena.service.LoginService;

@Controller
@RequestMapping("/login")
public class LoginController implements Serializable {
	
	@Resource
	private LoginService loginService;
	
	@ExceptionHandler
	public String execute(HttpServletRequest request,
			HttpServletResponse response, Exception e) throws Exception {
		if(e instanceof AdminCodeException
				|| e instanceof PasswordException) {
			//业务异常自己处理
			request.setAttribute("message", e.getMessage());
			request.setAttribute(
				"adminCode", request.getParameter("adminCode"));
			request.setAttribute(
				"password", request.getParameter("password"));
			return "main/login";
		} else {
			//系统异常抛出,交给Spring处理
			throw e;
		}
	}

	@RequestMapping("/toLogin.do")
	public String toLogin() {
		return "main/login";
	}
	
	@RequestMapping("/toIndex.do")
	public String toIndex() {
		return "main/index";
	}
	
	@RequestMapping("/checkLogin.do")
	public String checkLogin(String adminCode, String password, 
			ModelMap model, HttpSession session) {
//		try {
//			Admin admin = 
//				loginService.checkAdminCodeAndPwd(adminCode, password);
//			session.setAttribute("admin", admin);
//		} catch (AdminCodeException e) {
//			model.addAttribute("message", e.getMessage());
//			model.addAttribute("adminCode", adminCode);
//			model.addAttribute("password", password);
//			return "main/login";
//		} catch (PasswordException e) {
//			model.addAttribute("message", e.getMessage());
//			model.addAttribute("adminCode", adminCode);
//			model.addAttribute("password", password);
//			return "main/login";
//		}
		Integer.valueOf("abc");
		Admin admin = 
			loginService.checkAdminCodeAndPwd(adminCode, password);
		session.setAttribute("admin", admin);		
		return "redirect:toIndex.do";
	}
	
}

applicationContext.xml完整代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="/www.springframework.org/schema/beans" 
	xmlns:xsi="/www.w3.org/2001/XMLSchema-instance"
	xmlns:context="/www.springframework.org/schema/context" 
	xmlns:jdbc="/www.springframework.org/schema/jdbc"  
	xmlns:jee="/www.springframework.org/schema/jee" 
	xmlns:tx="/www.springframework.org/schema/tx"
	xmlns:aop="/www.springframework.org/schema/aop" 
	xmlns:mvc="/www.springframework.org/schema/mvc"
	xmlns:util="/www.springframework.org/schema/util"
	xmlns:jpa="/www.springframework.org/schema/data/jpa"
	xsi:schemaLocation="
		/www.springframework.org/schema/beans /www.springframework.org/schema/beans/spring-beans-3.2.xsd
		/www.springframework.org/schema/context /www.springframework.org/schema/context/spring-context-3.2.xsd
		/www.springframework.org/schema/jdbc /www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
		/www.springframework.org/schema/jee /www.springframework.org/schema/jee/spring-jee-3.2.xsd
		/www.springframework.org/schema/tx /www.springframework.org/schema/tx/spring-tx-3.2.xsd
		/www.springframework.org/schema/data/jpa /www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		/www.springframework.org/schema/aop /www.springframework.org/schema/aop/spring-aop-3.2.xsd
		/www.springframework.org/schema/mvc /www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		/www.springframework.org/schema/util /www.springframework.org/schema/util/spring-util-3.2.xsd">
	
	<util:properties id="jdbc" location="classpath:jdbc.properties"/>
	
	<!-- 定义数据源 -->
	<bean id="ds" 
		class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="url" value="#{jdbc.url}"/>
		<property name="driverClassName" value="#{jdbc.driver}"/>
		<property name="username" value="#{jdbc.user}"/>
		<property name="password" value="#{jdbc.password}"/>
	</bean>	
	
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>
	
	<!-- 开启MVC注解扫描 -->
	<mvc:annotation-driven/>
	
	<!-- 定义视图解析器ViewResolver -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/"/>
		<property name="suffix" value=".jsp"/>
	</bean>
	
	<!-- 处理系统异常 -->
	<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<property name="exceptionMappings">
	<props>		
	<prop key="java.lang.Exception">main/error</prop>
	</props>
	</property>
	</bean>	
	
</beans>

error.jsp完整代码如下:

<%@page pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "/www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="/www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title> -NetCTOSS</title>
<link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" />
<link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" />
<script language="javascript" type="text/javascript">
var timer;
            //启动跳转的定时器
function startTimes() {
timer = window.setInterval(showSecondes,1000);
            }

var i = 5;
function showSecondes() {
if (i > 0) {
i--;
document.getElementById("secondes").innerHTML = i;
                }
else {
window.clearInterval(timer);
                    //location.href = "login.html";
history.back();
                }
            }

            //取消跳转
function resetTimer() {
if (timer != null && timer != undefined) {
window.clearInterval(timer);
                    //location.href = "login.html";
history.back();
                }
            }
</script>
</head>
<body class="error_page" onload="startTimes();">
<h1 id="error">
	        遇到错误,&nbsp;<span id="secondes">5</span>&nbsp;秒后将自动跳转,立即跳转请点击&nbsp;
<a  href="javascript:resetTimer();">返回</a>
</h1>
</body>
</html>

4 资费列表

4.1 问题

实现NETCTOSS项目中资费列表功能。

4.2 方案

开发步骤:

  1. 在数据访问层增加查询全部资费的方法
  2. 在业务层增加查询资费的业务方法
  3. 在控制层增加处理查询请求的方法
  4. 在页面上使用JSTL+EL循环输出数据

4.3 步骤

步骤一:在DAO中增加查询资费的方法

创建资费表,并插入预置数据,代码如下:

--资费信息表
create table cost(
	cost_id			number(4) constraint cost_id_pk primary key,
	name			varchar(50)  not null,
	base_duration	number(11),
	base_cost		number(7,2),
	unit_cost		number(7,4),
	status			char(1),
	descr			varchar2(100),
	creatime		date default sysdate ,
	startime		date,
		cost_type		char(1)
  );

create sequence cost_seq start with 100;

INSERT INTO COST VALUES (1,'5.9元套餐',20,5.9,0.4,0,'5.9元20小时/月,超出部分0.4元/时',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (2,'6.9元套餐',40,6.9,0.3,0,'6.9元40小时/月,超出部分0.3元/时',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (3,'8.5元套餐',100,8.5,0.2,0,'8.5元100小时/月,超出部分0.2元/时',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (4,'10.5元套餐',200,10.5,0.1,0,'10.5元200小时/月,超出部分0.1元/时',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (5,'计时收费',null,null,0.5,0,'0.5元/时,不使用不收费',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (6,'包月',null,20,null,0,'每月20元,不限制使用时间',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (7,'mm',10,5,null,0,'',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (8,'nn',10,7,null,0,'',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (9,'qq',10,4,null,0,'',DEFAULT,DEFAULT,NULL);
COMMIT;

创建资费实体类Cost,代码如下:

package com.tarena.entity;

import java.io.Serializable;
import java.sql.Timestamp;

public class Cost implements Serializable {

	private Integer costId;
	private String name;
	private Integer baseDuration;
	private Double baseCost;
	private Double unitCost;
	private String status;
	private String descr;
	private Timestamp creatime;
	private Timestamp startime;
	private String costType;

	public Integer getCostId() {
		return costId;
	}

	public void setCostId(Integer costId) {
		this.costId = costId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getBaseDuration() {
		return baseDuration;
	}

	public void setBaseDuration(Integer baseDuration) {
		this.baseDuration = baseDuration;
	}

	public Double getBaseCost() {
		return baseCost;
	}

	public void setBaseCost(Double baseCost) {
		this.baseCost = baseCost;
	}

	public Double getUnitCost() {
		return unitCost;
	}

	public void setUnitCost(Double unitCost) {
		this.unitCost = unitCost;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getDescr() {
		return descr;
	}

	public void setDescr(String descr) {
		this.descr = descr;
	}

	public Timestamp getCreatime() {
		return creatime;
	}

	public void setCreatime(Timestamp creatime) {
		this.creatime = creatime;
	}

	public Timestamp getStartime() {
		return startime;
	}

	public void setStartime(Timestamp startime) {
		this.startime = startime;
	}

	public String getCostType() {
		return costType;
	}

	public void setCostType(String costType) {
		this.costType = costType;
	}

}

创建资费数据访问接口CostDao,代码如下:

package com.tarena.dao;

import java.util.List;

import com.tarena.entity.Cost;

public interface CostDao {
	
	List<Cost>findAll();

}

创建数据访问接口实现类JdbcCostDao,代码如下:

package com.tarena.dao;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.springframework.stereotype.Repository;

import com.tarena.entity.Cost;

@Repository
public class JdbcCostDao implements CostDao, Serializable {
	
	@Resource
	private DataSource dataSource;

	@Override
	public List<Cost> findAll() {
		List<Cost> list = new ArrayList<Cost>();
		Connection conn = null;
		try {
			conn = dataSource.getConnection();
			String sql = "select * from cost order by cost_id";
			PreparedStatement ps = conn.prepareStatement(sql);
			ResultSet rs = ps.executeQuery();
			while(rs.next()) {
				Cost cost = new Cost();
				cost.setCostId(rs.getInt("cost_id"));
				cost.setName(rs.getString("name"));
				cost.setBaseDuration(rs.getInt("base_duration"));
				cost.setBaseCost(rs.getDouble("base_cost"));
				cost.setUnitCost(rs.getDouble("unit_cost"));
				cost.setStatus(rs.getString("status"));
				cost.setDescr(rs.getString("descr"));
				cost.setCreatime(rs.getTimestamp("creatime"));
				cost.setStartime(rs.getTimestamp("startime"));
				cost.setCostType(rs.getString("cost_type"));
				list.add(cost);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException("查询资费失败", e);
		} finally {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return list;
	}

}

步骤二:在Service中增加查询业务方法

创建资费业务组件CostService,代码如下:

package com.tarena.service;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.tarena.dao.CostDao;
import com.tarena.entity.Cost;

@Service
public class CostService implements Serializable {
	
	@Resource
	private CostDao costDao;
	
	public List<Cost> findAll() {
		return costDao.findAll();
	}
}

步骤三:在Controller中处理查询请求

创建资费模块处理器CostController,代码如下:

package com.tarena.web;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import com.tarena.entity.Cost;
import com.tarena.service.CostService;

@Controller
@RequestMapping("/cost")
public class CostController implements Serializable {
	
	@Resource
	private CostService costService;
	
	@RequestMapping("/find.do")
	public String find(ModelMap model) {
		List<Cost> list = costService.findAll();
		model.addAttribute("costs", list);
		return "cost/cost_list";
	}

}

步骤四:资费列表页面

在WEB-INF/cost下创建资费列表页面cost_list.jsp,代码如下:

<%@page pageEncoding="utf-8"%>
<%@taglib uri="/java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "/www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="/www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title> </title>
<link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" />
<link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" />
<script language="javascript" type="text/javascript">
            //排序按钮的点击事件
function sort(btnObj) {
if (btnObj.className == "sort_desc")
                    btnObj.className = "sort_asc";
else
                    btnObj.className = "sort_desc";
            }

            //启用
function startFee() {
                var r = window.confirm("确定要启用此资费吗?资费启用后将不能修改和删除。");
document.getElementById("operate_result_info").style.display = "block";
            }
            //删除
function deleteFee() {
                var r = window.confirm("确定要删除此资费吗?");
document.getElementById("operate_result_info").style.display = "block";
            }
</script>
</head>
<body>
<!--Logo区域开始-->
<div id="header">
<img src="../images/logo.png" alt="logo" class="left"/>
<a href="#">[退出]</a>
</div>
<!--Logo区域结束-->
<!--导航区域开始-->
<div id="navi">
<ul id="menu">
<li><a href="../index.html" class="index_off"></a></li>
<li><a href="../role/role_list.html" class="role_off"></a></li>
<li><a href="../admin/admin_list.html" class="admin_off"></a></li>
<li><a href="../fee/fee_list.html" class="fee_on"></a></li>
<li><a href="../account/account_list.html" class="account_off"></a></li>
<li><a href="../service/service_list.html" class="service_off"></a></li>
<li><a href="../bill/bill_list.html" class="bill_off"></a></li>
<li><a href="../report/report_list.html" class="report_off"></a></li>
<li><a href="../user/user_info.html" class="information_off"></a></li>
<li><a href="../user/user_modi_pwd.html" class="password_off"></a></li>
</ul>
</div>
<!--导航区域结束-->
<!--主要区域开始-->
<div id="main">
<form action="" method="">
<!--排序-->
<div class="search_add">
<div>
<!--<input type="button" value="月租" class="sort_asc" onclick="sort(this);" />-->
<input type="button" value="基费" class="sort_asc" onclick="sort(this);" />
<input type="button" value="时长" class="sort_asc" onclick="sort(this);" />
</div>
<input type="button" value="增加" class="btn_add" onclick="location.href='fee_add.html';" />
</div>
<!--启用操作的操作提示-->
<div id="operate_result_info" class="operate_success">
<img src="../images/close.png" onclick="this.parentNode.style.display='none';" />
删除成功!
</div>
<!--数据区域:用表格展示数据-->
<div id="data">
<table id="datalist">
<tr>
<th>资费ID</th>
<th class="width100">资费名称</th>
<th>基本时长</th>
<th>基本费用</th>
<th>单位费用</th>
<th>创建时间</th>
<th>开通时间</th>
<th class="width50">状态</th>
<th class="width200"></th>
</tr>
<c:forEach items="${costs}" var="c">
<tr>
<td>${c.costId}</td>
<td><a href="fee_detail.html">${c.name}</a></td>
<td>${c.baseDuration}</td>
<td>${c.baseCost}</td>
<td>${c.unitCost}</td>
<td>${c.creatime}</td>
<td>${c.startime}</td>
<td>
	<c:if test="${c.status==0}">开通</c:if>
	<c:if test="${c.status==1}">暂停</c:if>
</td>
<td>
<input type="button" value="启用" class="btn_start" onclick="startFee();" />
<input type="button" value="修改" class="btn_modify" onclick="location.href='fee_modi.html';" />
<input type="button" value="删除" class="btn_delete" onclick="deleteFee();" />
</td>
</tr>
</c:forEach>
</table>
<p>业务说明:<br />
                    1、创建资费时,状态为暂停,记载创建时间;<br />
                    2、暂停状态下,可修改,可删除;<br />
                    3、开通后,记载开通时间,且开通后不能修改、不能再停用、也不能删除;<br />
                    4、业务账号修改资费时,在下月底统一触发,修改其关联的资费ID(此触发动作由程序处理)
</p>
</div>
<!--分页-->
<div id="pages">
	<a href="#">上一页</a>
<a href="#" class="current_page">1</a>
<a href="#">2</a>
<a href="#">3</a>
<a href="#">4</a>
<a href="#">5</a>
<a href="#">下一页</a>
</div>
</form>
</div>
<!--主要区域结束-->
<div id="footer">
<p>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</p>
<p>版权所有(C) </p>
</div>
</body>
</html>

步骤五:测试

部署项目并启动Tomcat,浏览器访问/localhost:8088/NETCTOSS2/cost/find.do,效果如下图:

图-9

4.4 完整代码

建表脚本完整代码如下:

--资费信息表
create table cost(
	cost_id			number(4) constraint cost_id_pk primary key,
	name			varchar(50)  not null,
	base_duration	number(11),
	base_cost		number(7,2),
	unit_cost		number(7,4),
	status			char(1),
	descr			varchar2(100),
	creatime		date default sysdate ,
	startime		date,
		cost_type		char(1)
  );

create sequence cost_seq start with 100;

INSERT INTO COST VALUES (1,'5.9元套餐',20,5.9,0.4,0,'5.9元20小时/月,超出部分0.4元/时',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (2,'6.9元套餐',40,6.9,0.3,0,'6.9元40小时/月,超出部分0.3元/时',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (3,'8.5元套餐',100,8.5,0.2,0,'8.5元100小时/月,超出部分0.2元/时',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (4,'10.5元套餐',200,10.5,0.1,0,'10.5元200小时/月,超出部分0.1元/时',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (5,'计时收费',null,null,0.5,0,'0.5元/时,不使用不收费',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (6,'包月',null,20,null,0,'每月20元,不限制使用时间',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (7,'mm',10,5,null,0,'',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (8,'nn',10,7,null,0,'',DEFAULT,DEFAULT,NULL);
INSERT INTO COST VALUES (9,'qq',10,4,null,0,'',DEFAULT,DEFAULT,NULL);
COMMIT;

Cost类完整代码如下:

package com.tarena.entity;

import java.io.Serializable;
import java.sql.Timestamp;

public class Cost implements Serializable {

	private Integer costId;
	private String name;
	private Integer baseDuration;
	private Double baseCost;
	private Double unitCost;
	private String status;
	private String descr;
	private Timestamp creatime;
	private Timestamp startime;
	private String costType;

	public Integer getCostId() {
		return costId;
	}

	public void setCostId(Integer costId) {
		this.costId = costId;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getBaseDuration() {
		return baseDuration;
	}

	public void setBaseDuration(Integer baseDuration) {
		this.baseDuration = baseDuration;
	}

	public Double getBaseCost() {
		return baseCost;
	}

	public void setBaseCost(Double baseCost) {
		this.baseCost = baseCost;
	}

	public Double getUnitCost() {
		return unitCost;
	}

	public void setUnitCost(Double unitCost) {
		this.unitCost = unitCost;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getDescr() {
		return descr;
	}

	public void setDescr(String descr) {
		this.descr = descr;
	}

	public Timestamp getCreatime() {
		return creatime;
	}

	public void setCreatime(Timestamp creatime) {
		this.creatime = creatime;
	}

	public Timestamp getStartime() {
		return startime;
	}

	public void setStartime(Timestamp startime) {
		this.startime = startime;
	}

	public String getCostType() {
		return costType;
	}

	public void setCostType(String costType) {
		this.costType = costType;
	}

}

CostDao完整代码如下:

package com.tarena.dao;

import java.util.List;

import com.tarena.entity.Cost;

public interface CostDao {
	
	List<Cost>findAll();

}

JdbcCostDao完整代码如下:

package com.tarena.dao;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.springframework.stereotype.Repository;

import com.tarena.entity.Cost;

@Repository
public class JdbcCostDao implements CostDao, Serializable {
	
	@Resource
	private DataSource dataSource;

	@Override
	public List<Cost> findAll() {
		List<Cost> list = new ArrayList<Cost>();
		Connection conn = null;
		try {
			conn = dataSource.getConnection();
			String sql = "select * from cost order by cost_id";
			PreparedStatement ps = conn.prepareStatement(sql);
			ResultSet rs = ps.executeQuery();
			while(rs.next()) {
				Cost cost = new Cost();
				cost.setCostId(rs.getInt("cost_id"));
				cost.setName(rs.getString("name"));
				cost.setBaseDuration(rs.getInt("base_duration"));
				cost.setBaseCost(rs.getDouble("base_cost"));
				cost.setUnitCost(rs.getDouble("unit_cost"));
				cost.setStatus(rs.getString("status"));
				cost.setDescr(rs.getString("descr"));
				cost.setCreatime(rs.getTimestamp("creatime"));
				cost.setStartime(rs.getTimestamp("startime"));
				cost.setCostType(rs.getString("cost_type"));
				list.add(cost);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException("查询资费失败", e);
		} finally {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return list;
	}

}

CostService完整代码如下:

package com.tarena.service;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.tarena.dao.CostDao;
import com.tarena.entity.Cost;

@Service
public class CostService implements Serializable {
	
	@Resource
	private CostDao costDao;
	
	public List<Cost> findAll() {
		return costDao.findAll();
	}
}

CostController完整代码如下:

package com.tarena.web;

import java.io.Serializable;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import com.tarena.entity.Cost;
import com.tarena.service.CostService;

@Controller
@RequestMapping("/cost")
public class CostController implements Serializable {
	
	@Resource
	private CostService costService;
	
	@RequestMapping("/find.do")
	public String find(ModelMap model) {
		List<Cost> list = costService.findAll();
		model.addAttribute("costs", list);
		return "cost/cost_list";
	}

}

cost_list.jsp完整代码如下:

<%@page pageEncoding="utf-8"%>
<%@taglib uri="/java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "/www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="/www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title> -NetCTOSS</title>
<link type="text/css" rel="stylesheet" media="all" href="../styles/global.css" />
<link type="text/css" rel="stylesheet" media="all" href="../styles/global_color.css" />
<script language="javascript" type="text/javascript">
            //排序按钮的点击事件
function sort(btnObj) {
if (btnObj.className == "sort_desc")
                    btnObj.className = "sort_asc";
else
                    btnObj.className = "sort_desc";
            }

            //启用
function startFee() {
                var r = window.confirm("确定要启用此资费吗?资费启用后将不能修改和删除。");
document.getElementById("operate_result_info").style.display = "block";
            }
            //删除
function deleteFee() {
                var r = window.confirm("确定要删除此资费吗?");
document.getElementById("operate_result_info").style.display = "block";
            }
</script>
</head>
<body>
<!--Logo区域开始-->
<div id="header">
<img src="../images/logo.png" alt="logo" class="left"/>
<a href="#">[退出]</a>
</div>
<!--Logo区域结束-->
<!--导航区域开始-->
<div id="navi">
<ul id="menu">
<li><a href="../index.html" class="index_off"></a></li>
<li><a href="../role/role_list.html" class="role_off"></a></li>
<li><a href="../admin/admin_list.html" class="admin_off"></a></li>
<li><a href="../fee/fee_list.html" class="fee_on"></a></li>
<li><a href="../account/account_list.html" class="account_off"></a></li>
<li><a href="../service/service_list.html" class="service_off"></a></li>
<li><a href="../bill/bill_list.html" class="bill_off"></a></li>
<li><a href="../report/report_list.html" class="report_off"></a></li>
<li><a href="../user/user_info.html" class="information_off"></a></li>
<li><a href="../user/user_modi_pwd.html" class="password_off"></a></li>
</ul>
</div>
<!--导航区域结束-->
<!--主要区域开始-->
<div id="main">
<form action="" method="">
<!--排序-->
<div class="search_add">
<div>
<!--<input type="button" value="月租" class="sort_asc" onclick="sort(this);" />-->
<input type="button" value="基费" class="sort_asc" onclick="sort(this);" />
<input type="button" value="时长" class="sort_asc" onclick="sort(this);" />
</div>
<input type="button" value="增加" class="btn_add" onclick="location.href='fee_add.html';" />
</div>
<!--启用操作的操作提示-->
<div id="operate_result_info" class="operate_success">
<img src="../images/close.png" onclick="this.parentNode.style.display='none';" />
                    删除成功!
</div>
<!--数据区域:用表格展示数据-->
<div id="data">
<table id="datalist">
<tr>
<th>资费ID</th>
<th class="width100">资费名称</th>
<th>基本时长</th>
<th>基本费用</th>
<th>单位费用</th>
<th>创建时间</th>
<th>开通时间</th>
<th class="width50">状态</th>
<th class="width200"></th>
</tr>
<c:forEach items="${costs}" var="c">
<tr>
<td>${c.costId}</td>
<td><a href="fee_detail.html">${c.name}</a></td>
<td>${c.baseDuration}</td>
<td>${c.baseCost}</td>
<td>${c.unitCost}</td>
<td>${c.creatime}</td>
<td>${c.startime}</td>
<td>
	<c:if test="${c.status==0}">开通</c:if>
	<c:if test="${c.status==1}">暂停</c:if>
</td>
<td>
<input type="button" value="启用" class="btn_start" onclick="startFee();" />
<input type="button" value="修改" class="btn_modify" onclick="location.href='fee_modi.html';" />
<input type="button" value="删除" class="btn_delete" onclick="deleteFee();" />
</td>
</tr>
</c:forEach>
</table>
<p>业务说明:<br />
                    1、创建资费时,状态为暂停,记载创建时间;<br />
                    2、暂停状态下,可修改,可删除;<br />
                    3、开通后,记载开通时间,且开通后不能修改、不能再停用、也不能删除;<br />
                    4、业务账号修改资费时,在下月底统一触发,修改其关联的资费ID(此触发动作由程序处理)
</p>
</div>
<!--分页-->
<div id="pages">
	<a href="#">上一页</a>
<a href="#" class="current_page">1</a>
<a href="#">2</a>
<a href="#">3</a>
<a href="#">4</a>
<a href="#">5</a>
<a href="#">下一页</a>
</div>
</form>
</div>
<!--主要区域结束-->
<div id="footer">
<p>[源自北美的技术,最优秀的师资,最真实的企业环境,最适用的实战项目]</p>
<p>版权所有(C)  </p>
</div>
</body>
</html>

5 拦截器案例

5.1 问题

在Spring05项目中,使用拦截器扩展HelloController,在HelloController执行前、后各输出一句话。

5.2 方案

拦截器使用步骤:

  1. 创建拦截器组件,实现HandlerInterceptor接口
  2. 注册拦截器组件

5.3 步骤

步骤一:创建拦截器

创建拦截器组件FirstInterceptor,代码如下:

package com.tarena.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class FirstInterceptor implements HandlerInterceptor {

	@Override
	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("afterCompletion");
	}

	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2, ModelAndView arg3) throws Exception {
		System.out.println("postHandle");
	}

	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2) throws Exception {
		System.out.println("preHandle");
		return true;
	}

}

步骤二:注册拦截器

在spring-mvc.xml中注册拦截器,追加代码如下:

	<!--拦截器 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<bean class="com.tarena.web.FirstInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>

步骤三:测试

在HelloController中增加一个方法,输出一句话,并将请求转发到hello.jsp,追加代码如下:

	@RequestMapping("/nihao.do")
	public String nihao() {
		System.out.println("你好");
		return "jsp/hello";
	}

部署项目并启动Tomcat,浏览器访问/localhost:8088/Spring05/demo/nihao.do,控制台输出结果如下图:

图-10

5.4 完整代码

FirstInterceptor完整代码如下:

package com.tarena.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class FirstInterceptor implements HandlerInterceptor {

	@Override
	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		System.out.println("afterCompletion");
	}

	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2, ModelAndView arg3) throws Exception {
		System.out.println("postHandle");
	}

	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2) throws Exception {
		System.out.println("preHandle");
		return true;
	}

}

spring-mvc.xml完整代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="/www.springframework.org/schema/beans" 
	xmlns:xsi="/www.w3.org/2001/XMLSchema-instance"
	xmlns:context="/www.springframework.org/schema/context" 
	xmlns:jdbc="/www.springframework.org/schema/jdbc"  
	xmlns:jee="/www.springframework.org/schema/jee" 
	xmlns:tx="/www.springframework.org/schema/tx"
	xmlns:aop="/www.springframework.org/schema/aop" 
	xmlns:mvc="/www.springframework.org/schema/mvc"
	xmlns:util="/www.springframework.org/schema/util"
	xmlns:jpa="/www.springframework.org/schema/data/jpa"
	xsi:schemaLocation="
		/www.springframework.org/schema/beans /www.springframework.org/schema/beans/spring-beans-3.2.xsd
		/www.springframework.org/schema/context /www.springframework.org/schema/context/spring-context-3.2.xsd
		/www.springframework.org/schema/jdbc /www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
		/www.springframework.org/schema/jee /www.springframework.org/schema/jee/spring-jee-3.2.xsd
		/www.springframework.org/schema/tx /www.springframework.org/schema/tx/spring-tx-3.2.xsd
		/www.springframework.org/schema/data/jpa /www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		/www.springframework.org/schema/aop /www.springframework.org/schema/aop/spring-aop-3.2.xsd
		/www.springframework.org/schema/mvc /www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		/www.springframework.org/schema/util /www.springframework.org/schema/util/spring-util-3.2.xsd">
	
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>
	
	<!-- 开启MVC注解扫描 -->
	<mvc:annotation-driven/>
	
	<!-- 定义视图解析器ViewResolver -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/"/>
		<property name="suffix" value=".jsp"/>
	</bean>
	
	<!-- 处理系统异常 -->
	<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<property name="exceptionMappings">
	<props>		
	<prop key="java.lang.Exception">jsp/error</prop>
	</props>
	</property>
	</bean>
	
	<!-- 拦截器 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<bean class="com.tarena.web.FirstInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>
	
</beans>

HelloController完整代码如下:

package com.tarena.web;

import java.io.Serializable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/demo")
public class HelloController implements Serializable {
	
	@ExceptionHandler
	public String handleException(Exception e, 
		HttpServletRequest request, HttpServletResponse response) 
		throws Exception {
		if(e instanceof NumberFormatException) {
			request.setAttribute("message", "亲,请输入数字哦.");
			return "jsp/message";
		} else {
			throw e;
		}
	}
	
	@RequestMapping("/hello.do")
	public String hello() {
		System.out.println("hello");
		Integer.valueOf("abc");
		return "jsp/hello";
	}
	
	@RequestMapping("/hi.do")
	public String hi() {
		System.out.println("hi");
		String name = "abc";
		name.charAt(9);
		return "jsp/hello";
	}

	@RequestMapping("/nihao.do")
	public String nihao() {
		System.out.println("你好");
		return "jsp/hello";
	}
	
}

6 登录检查

6.1 问题

访问NETCTOSS资费等业务功能时,检查用户是否已经登录,若未登录则强制页面跳转至登录页面。

6.2 方案

使用拦截器,拦截除了登录之外的所有请求,并判断session中是否存在登录信息,若不存在则重定向到登录页面。

6.3 步骤

步骤一:创建登录检查拦截器

创建登录检查拦截器LoginInterceptor,代码如下:

package com.tarena.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.tarena.entity.Admin;

public class LoginInterceptor implements HandlerInterceptor {

	@Override
	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {

	}

	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2, ModelAndView arg3) throws Exception {

	}

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object arg2) throws Exception {
		Admin admin = (Admin) 
			request.getSession().getAttribute("admin");
		if(admin == null) {
			response.sendRedirect(
				request.getContextPath() + "/login/toLogin.do");
			return false;
		}
		return true;
	}

}

步骤二:注册拦截器

在applicationContext.xml中注册该拦截器,追加代码如下:

	<!--拦截器 -->
	<mvc:interceptors>
		<!--登录检查拦截器 -->
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<mvc:exclude-mapping path="/login/toLogin.do"/>
			<mvc:exclude-mapping path="/login/checkLogin.do"/>
			<bean class="com.tarena.web.LoginInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>

步骤三:测试

部署NETCTOSS项目并启动Tomcat,浏览器输入地址访问资费列表功能,浏览器显示结果如下图:

图-11

输入正确的账号、密码,登录NETCTOSS,然后再次输入地址访问资费列表功能,浏览器显示结果如下图:

图-12

6.4 完整代码

LoginInterceptor完整代码如下:

package com.tarena.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.tarena.entity.Admin;

public class LoginInterceptor implements HandlerInterceptor {

	@Override
	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {

	}

	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object arg2, ModelAndView arg3) throws Exception {

	}

	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object arg2) throws Exception {
		Admin admin = (Admin) 
			request.getSession().getAttribute("admin");
		if(admin == null) {
			response.sendRedirect(
				request.getContextPath() + "/login/toLogin.do");
			return false;
		}
		return true;
	}

}

applicationContext.xml完整代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="/www.springframework.org/schema/beans" 
	xmlns:xsi="/www.w3.org/2001/XMLSchema-instance"
	xmlns:context="/www.springframework.org/schema/context" 
	xmlns:jdbc="/www.springframework.org/schema/jdbc"  
	xmlns:jee="/www.springframework.org/schema/jee" 
	xmlns:tx="/www.springframework.org/schema/tx"
	xmlns:aop="/www.springframework.org/schema/aop" 
	xmlns:mvc="/www.springframework.org/schema/mvc"
	xmlns:util="/www.springframework.org/schema/util"
	xmlns:jpa="/www.springframework.org/schema/data/jpa"
	xsi:schemaLocation="
		/www.springframework.org/schema/beans /www.springframework.org/schema/beans/spring-beans-3.2.xsd
		/www.springframework.org/schema/context /www.springframework.org/schema/context/spring-context-3.2.xsd
		/www.springframework.org/schema/jdbc /www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
		/www.springframework.org/schema/jee /www.springframework.org/schema/jee/spring-jee-3.2.xsd
		/www.springframework.org/schema/tx /www.springframework.org/schema/tx/spring-tx-3.2.xsd
		/www.springframework.org/schema/data/jpa /www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		/www.springframework.org/schema/aop /www.springframework.org/schema/aop/spring-aop-3.2.xsd
		/www.springframework.org/schema/mvc /www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		/www.springframework.org/schema/util /www.springframework.org/schema/util/spring-util-3.2.xsd">
	
	<util:properties id="jdbc" location="classpath:jdbc.properties"/>
	
	<!-- 定义数据源 -->
	<bean id="ds" 
		class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="url" value="#{jdbc.url}"/>
		<property name="driverClassName" value="#{jdbc.driver}"/>
		<property name="username" value="#{jdbc.user}"/>
		<property name="password" value="#{jdbc.password}"/>
	</bean>	
	
	<!-- 开启注解扫描 -->
	<context:component-scan base-package="com.tarena"/>
	
	<!-- 开启MVC注解扫描 -->
	<mvc:annotation-driven/>
	
	<!-- 定义视图解析器ViewResolver -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/"/>
		<property name="suffix" value=".jsp"/>
	</bean>
	
	<!-- 处理系统异常 -->
	<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		<property name="exceptionMappings">
	<props>		
	<prop key="java.lang.Exception">main/error</prop>
	</props>
	</property>
	</bean>	
	
	<!-- 拦截器 -->
	<mvc:interceptors>
		<!-- 登录检查拦截器 -->
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<mvc:exclude-mapping path="/login/toLogin.do"/>
			<mvc:exclude-mapping path="/login/checkLogin.do"/>
			<bean class="com.tarena.web.LoginInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>
	
</beans>