控制器层及前端页面
在cn.tedu.spring.controller.UserController类,添加处理登录请求的方法:
@RequestMapping(
method=RequestMethod.POST,
value="/handleRegister.do")
public String handleRegister(User user) {
}
由于实现注册时,需要使用Service,所以,在类中声明private IUserService userService,并使用@Resource进行注解,这样的话,在handleRegister中,就可以调用Service对象来完成注册!
当调用Service执行注册时,应该获取返回值,并对其进行判断,如果结果为-1,表示用户名已经存在,注册失败,否则,注册成功,为了保证能够很好的显示最终结果,应该设计前端页面!
创建error.jsp表示操作错误的提示页面,在该页面中,通过${errorMessage}提示错误信息。
创建login.jsp表示登录页面,其内容可以直接从现有的register.jsp中复制,删除原注册表单中的手机号码、电子邮件,修改表示提交到的路径,及相关文字。
完成前端页面后,如果在handleReigster方法中得到的结果是注册成功,则直接return “redirect:login.do”;,如果得到的结果是注册失败,则需要先在当前方法中添加ModelMap参数,并向该参数中封装名为errorMessage的数据,内容是对错误信息的描述,最后,返回return “error”。
最后,在UserController中,添加方法,对/login.do路径进行处理,转发到login.jsp页面。
项目开发流程
1 创建项目,完成基本配置
2 总体设计:规划数据库与数据表
3 创建数据库与数据表
4 创建与数据表结构匹配的实体类
5 设计目标:页面请求路径、处理功能路径、响应页面路径
6 设计前端页面
7 处理Model-持久层,并单元测试
8 处理Model-业务层,并单元测试
9 处理控制器层
10 整合测试
乱码问题
1 为什么可能出现乱码
出现乱码的唯一原因就是编码不统一!解决乱码问题的唯一做法就是使用统一的某1种支持中文的编码格式!
2 在哪些位置需要确定编码
取决于数据的传递过程会接触到哪些位置!
包括:程序的源代码、前端页面、数据库、程序与数据库之间的连接
其中,程序的源代码的编码格式可以设置开发工具的默认编码,或每次创建项目后检查并设置。
前端页面如果显示乱码(确定问题出在前端页面),可以通过配置标签来解决:,如果前端页面是通过.jsp文件来生成的,则还应该:<%@ page contentType=“text/html; charset=utf-8” pageEncoding=“utf-8”%>
对于普通的GET请求,还应该配置Tomcat的默认处理编码格式,即在conf\server.xml文件中,查询8080关键字,在其所在的节点中添加URIEncoding="utf-8"即可。
3 Spring MVC中的CharacterEncodingFilter
不要尝试通过Controller中使用HttpServletRequest解决乱码问题,因为,如果编码不统一,在Spring MVC的DispatcherServlet中就已经出现乱码了,而Controllner是在DispatcherServlet之后运行的,所以无法解决已经存在的乱码。
在Spring MVC中,已经定义了CharacterEncodingFilter这个过滤器,很显然,在Java WEB项目,Filter是在Servlet之前运行的,所以,当解决View -> Controller这个过程中的乱码问题时,只需要在web.xml中配置该过滤器即可:
CharacterEncodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding utf-8 CharacterEncodingFilter *.do 4 MySQL乱码问题 最权威的解决方案:删除以后重新安装!注意:在MySQL的安装完成后,第1次运行配置向导时,会要求指定数据库默认编码,此时一定仔细确认!
在MySQL控制台中,输入\s即可查看当前MySQL的编码设置情况。
如果一定要在现有的MySQL中解决问题,首先,每次创建数据库与数据表时都明显的指定编码格式,例如:
CREATE TABLE xxx (字段设计……) DEFAULT CHARSET=UTF8;
为了避免数据从Tomcat服务器到MySQL服务器的过程中可能出现乱码,应该在数据库连接的url后添加参数:?useUnicode=true&characterEncoding=utf8
Spring中的拦截器(Interceptor)
1 基本概念
拦截器(Interceptor)是运行在DispatcherServlet之后,在每个Controller之前的一个组件。
通过配置拦截器,可以使得满足配置条件的请求都必须先经过拦截器,才可以被Controller中处理请求的方法来处理,所以,拦截器具有“拦截”和“放行”的功能。
对于许多处理请求时都需要执行的任务,就可以通过拦截器来处理,例如验证用户是否登录。
2 开发步骤
2.1 准备工作
设计请求路径:
http://SERVER:PORT/PROJECT/index.do(主页)
http://SERVER:PORT/PROJECT/login.do(登录页)
http://SERVER:PORT/PROJECT/user_center.do(用户中心页)
创建cn.tedu.spring.controller.MainController,添加3个方法:
showIndex()
showLogin()
showUserCenter()
分别用于处理以上3种请求,并分别转发到WEB-INF/index.jsp、WEB-INF/login.jsp他WEB-INF/user_center.jsp,每个页面中都添加一段文字表示当前页面。
2.2 创建拦截器类
创建cn.tedu.spring.interceptor.SampleInterceptor,实现HandlerInterceptor接口,重写其中的抽象方法。
2.3 配置拦截器
在spring-mvc.xml文件中配置:
mvc:interceptors
mvc:interceptor
<mvc:mapping path="/*"/>
</mvc:interceptor>
</mvc:interceptors>
注意:配置时需要区分先后顺序,必须最先配置<mvc:mapping />,最后配置。
3 详细介绍
3.1 3个抽象方法
只有preHandle()会在Controller处理请求之前运行,另2个方法都会在处理请求之后运行!
3.2 【重要】preHandle()方法
该方法的返回值是boolean类型,返回false时表示拦截,返回true时表示放行。
3.3 postHandle()方法
当Controller处理完请求之后,postHandle()方法就会被运行,其中,ModelAndView对象中会封装后续处理的View组件名称和转发的数据。
3.3 afterCompletion()方法
最后运行的方法。
4 进阶测试
4.1 需求
创建新的拦截器SessionInterceptor,要求只对user_center.do进行拦截,另2个不拦截(不处理)。
4.2 解决方案
如果只是少量的请求需要被拦截,可以:
<mvc:mapping path="/user_center.do" />
但是,这样做的缺点在于难以应付许多请求都需要被拦截。则可以在spring-mvc.xml中配置拦截器时,使用<mvc:exclude-mapping />节点配置例外,也就是在<mvc:mapping />的基础之上添加例外!
<mvc:mapping path="/*" />
<mvc:exclude-mapping path="/login.do" />
<mvc:exclude-mapping path="/index.do" />
在以上配置中,需要注意:必须先配置<mvc:mapping />然后再配置<mvc:exclude-mapping />!
以上配置中,如果添加了例如,则当服务器接收到例外请求时,拦截器根本就不运行!更不存在放行或拦截的问题。
注意:使用/*只能表示匹配根路径下的所有内容!如果有子级,则匹配不上,例如可以匹配/login.do和/index.do,却不能匹配到/user/???.do,如果需要匹配根路径及各层级子级路径,需要使用/**才可以!
5 拦截器链
与Filter类似,在Spring MVC中的拦截器也可以存在多个,并且形成拦截器链,仅当所有匹配的拦截器的preHandle()都执行之后,才会调用Controller中处理请求的方法,然后再执行所有匹配的拦截器的postHandler(),再执行所有匹配的拦截器的afterCompletion()。
在拦截器链中,各拦截器的执行先后顺序取决于配置文件中配置的节点的先后顺序!
6 练习:登录过滤器
6.1 设计目标
如果已经登录,可以正常访问user/user_center.do
如果没有登录,当访问user/user_center.do时,将自动重定向到login.do
6.2 准备工作
新建UserController,使用@RequestMapping("/user")和@Controller注解,并将原来在MainController中的showUserCenter()方法剪切到UserController中。
将spring-mvc.xml中通配符都设置为/**。
在login.jsp中添加和,提交到http://SERVER:PORT/PROJECT/user/handle_login.do。
则在UserController中添加方法以处理以上请求:
@RequestMapping(value="/handle_login.do",
method=RequestMethod.POST)
public String handleLogin(HttpSession session) {
session.setAttribute(“uid”, 9527);
return “redirect:user_center.do”;
}
在user_center.jsp中显示Session信息。
为了便于测试,还应该在user_center.jsp中添加“退出登录”功能。则在该页面中添加退出登录,并在UserController中添加方法以处理这个新的请求:
@RequestMapping(“logout.do”)
public String handleLogout(HttpSession session) {
session.invalidate();
return “redirect:…/login.do”;
}
6.3 实现拦截
检查拦截器是否能匹配相关的路径,及不处理不必要的路径。特别是user/handle_login.do必须添加为不处理!
拦截的标准就是:判断Session中是否存在名为uid的值,如果存在,表示已经登录,如果不存在,则表示没有登录!
编写拦截功能的方法显然是preHandle()方法,代码示例:
// 获取Session信息
HttpSession session = request.getSession();
// 检查Session中是否有登录信息
if (session.getAttribute(“uid”) == null) {
// 确定重定向的目标位置
String url = request.getContextPath() + “/login.do”;
// 没有登录,则重定向
response.sendRedirect(url);
// 返回
return false;
} else {
// 已经登录,则放行
}
7 小结
【何时使用】当处理多种请求都需要执行相同或极为相似的代码时,应该使用拦截器,并且将这些代码编写在拦截器中,在编写时,可能使用preHandle()方法!
【如何配置】如果只有极少量的请求需要使用拦截器,则使用多个<mvc:mapping />配置这些请求路径就可以!如果有大量请求都需要使用拦截器,却只有少量请求不使用,则应该使用<mvc:mapping />配置通配符,再添加若干个<mvc:exclude-mapping />以配置例外!如果业务分明,甚至可以配置拦截器只匹配指定的路径,例如:<mvc:mapping path="/user/**" />,合理的使用路径,可以简化拦截器的配置。
【拦截器与过滤器】这两者最大的区别在于:过滤器会在DispatcherServlet之前运行,意味着可以对所有的请求进行处理!拦截器会在DispatcherServlet之后运行,也就是说只能对的web.xml中配置DispatcherServlet时的映射的路径进行处理!
小结
1 在开发项目之前,请认真的检查所有关于编码的问题,包括:项目源码的编码、数据库与数据表的编码(保证每次创建数据表时都添加DEFAULT CHARSET=UTF8)、TOMCAT的编码(配置8080端口的节点上的URIEncoding=“utf-8”)、连接数据库的url(添加?useUnicode=true&characterEncoding=utf-8)、配置Spring中的CharacterEncodingFilter(固定配置),并在后续每一个前端页面都配置编码为UTF-8,就不会出现乱码问题。