这个系列专栏的完结可能比我想象要快一些。不过可能将来要完善这个项目的时候还会加以改进。我今天争取把最后一层:控制层的代码给写完。明天最后一篇博文将讲讲Session、cookie对用户登录的控制,并最后完善一下前端页面,这个专栏的主要内容就算完结了。
一、Spring MVC的配置
首先,写一下spring mvc的配置文件dispatcher-servlet.xml:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
基本跟spring的配置文件一样。注释给得全,没什么值得解释的。值得注意的是jspViewResolver这个bean。这个视图解析器主要工作是返回解析的视图给控制层。在本项目中,前缀为“/”,后缀为“.jsp”的视图都会被spring mvc检测到。
二、控制层
然后就是控制层的代码了。首先是登录功能。这个项目中所有的表单提交方式我都准备用ajax提交表单。form提交适合进行页面跳转的操作,但ajax可以局部刷新,响应速度比较快,而且能从不同的html控件中通过js获取值。因此相对而言,ajax是页面数据传输的首选方式。
按照我的习惯,先从controller层开始写。首先UserController要实现的功能有:注册、登录验证。很好写。
首先,要把前几篇文章没填完的坑填上:
1、在BlogDAO实现根据用户id查询文章列表的操作:
/*** 根据用户id查询文章列表* @param uid 用户id* @return List 返回Blog列表*/
public List findByUid(int uid) {
return this.getHibernateTemplate().execute(new HibernateCallback>() {
@Transactional
public List doInHibernate(Session session) {
Query query = session.createQuery("from Blog where userid=" + uid);
return query.list();
}
});
}2、UserDAO里实现根据用户名查询用户:
/*** 根据用户名查询用户* @param username 用户名* @return List 返回Blog列表*/
public List findByUsername(String username) {
return this.getHibernateTemplate().execute(new HibernateCallback>() {
@Transactional
public List doInHibernate(Session session) {
Query query = session.createQuery("from User where username=" + username);
return query.list();
}
});
}
配置完毕。下面进入正题。
一、UserController实现:
现在可以来实现UserController了:
package org.caihaolun.controller;
import org.caihaolun.dao.UserDAO;
import org.caihaolun.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/*** Created by Administrator on 2017/4/3.* 控制层*/
@Controller
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class UserController {
private UserDAO userDAO;
@Resource
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
private static void addCookie(String name, String value, int maxAge, HttpServletResponse response) throws Exception {
//添加cookie操作 Cookie cookie = new Cookie(name, URLEncoder.encode(value.trim(), "UTF-8"));
cookie.setMaxAge(maxAge);// 设置为10天 cookie.setPath("/");
System.out.println("已添加" + name);
response.addCookie(cookie);
}
@RequestMapping(value = "/", method = RequestMethod.GET)
public String index() {
return "login";
}
@RequestMapping(value = "/validate", method = RequestMethod.POST)
@ResponseBody
public Map validate(@RequestBody User user, HttpServletResponse response) throws Exception {
Map map = new HashMap<>();
User user1 = userDAO.findByID(user.getUid());
//登录成功返回user,失败返回null if (user1 == null || !user1.getUsername().equals(user.getUsername())) {
map.put("result", "用户名不正确!");
return map;
} else if (!user1.getPassword().equals(user.getPassword())) {
map.put("result", "密码不正确!");
return map;
} else {
map.put("result", "SUCCESS");
addCookie("uid", user1.getUid().toString(), 10 * 24 * 60 * 60, response);
addCookie("username", user1.getUsername(), 10 * 24 * 60 * 60, response);
return map;
}
}
@RequestMapping(value = "/register", method = RequestMethod.POST)
@ResponseBody
public Map register(@RequestBody User user, HttpServletResponse response) throws Exception {
Map result = new HashMap<>();
userDAO.save(user);
addCookie("uid", user.getUid().toString(), 10 * 24 * 60 * 60, response);
addCookie("username", user.getUsername(), 10 * 24 * 60 * 60, response);
result.put("result", "SUCCESS");
return result;
}
}
这里就稍微解释一下:
1、@RequestMapping注解意为:表现层请求的路径对应RequestMapping中的value值,才可以把这个请求传递到后台的控制层。并且还可以定义RequestMethod为GET或POST。然后可以通过@RequestBody把一个封装好的对象传递到后台控制层。
2、@ResponseBody:由于ajax无法直接接收到返回的String类型,因此要把类型封装成map,便于前台的jQuery接收返回参数。
3、addCookie:添加cookie操作。由于HTTP协议是无状态的协议,所以客户端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是cookie。这里我把uid和username添加进cookie并加进response返回前台。本来服务器端需要用Session保存用户信息的,但这篇文章中暂时不使用Session。
然后就是前台ajax的编程:
1、首先是注册页面:
$(document).ready(function () {
var uname_ = $.cookie("username");
$("#register-button").click(function () {
var id = $("#id-reg").val();
var username = $("#username-reg").val();
var password = $("#password1").val();
var repassword = $("#password2").val();
if (password != repassword) {
alert("密码与确认密码不一致!");
} else if (id == "" || username == "" || password == "") {
alert("请确认是否有空缺项!");
} else {
var user = {
"uid": id,
"username": username,
"password": password
};
$.ajax({
type: 'post',
url: 'register',
contentType: 'application/json;charset=utf-8',
data: JSON.stringify(user),
success: function (data) {
if (data["result"] == "SUCCESS") {
alert("注册成功!");
$("#top_menu").html
('
'
' +'
' + uname_ + '
' +'修改密码' +
' ' +
'注销
');$("#myDiv").load("articleList.jsp");
} else {
alert("注册失败!" + data["result"]);
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.status);
alert(XMLHttpRequest.readyState);
alert(textStatus);
alert(errorThrown);
}
});
}
})
})
在$.post中,如果最后一个参数(表示接收返回值的类型)填的是json,那么data["result"]就可直接引用返回的map中对应键的值。
注意一下,这里的uname_值是从cookie中拿进来的。需要导入的js引用。而且引用顺序一定是在jQuery之后!!
这是原来的那个主页:
这里ajax提交成功之后改变的就是top_menu这块div中的html。
2、然后登录页面:
$(document).ready(function () {
var uname = $.cookie("username");
$("#register_").click(function () {
$("#myDiv").load("register.jsp");
});
$("#login_").click(function () {
var uid = $("#uid").val();
var username = $("#username").val();
var password = $("#password").val();
if (uid == "" || username == "" || password == "") {
alert("请确认是否有空缺项!");
} else {
var user_ = {
"uid": uid,
"username": username,
"password": password
};
$.ajax({
type: 'post',
url: 'validate',
contentType: 'application/json;charset=utf-8',
data: JSON.stringify(user_),
success: function (data) {
if (data["result"] == "SUCCESS") {
alert("登陆成功!");
$("#top_menu").html
('
'
' +'
' + uname + '
' +'修改密码' +
' ' +
'注销
');$("#myDiv").load("articleList.jsp");
} else {
alert("登录失败!" + data["result"]);
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.status);
alert(XMLHttpRequest.readyState);
alert(textStatus);
alert(errorThrown);
}
});
}
});
});
同理,不赘述。
效果:
登录页面同样。读者可以自行试验。
二、BlogController实现
博客就那几个操作:增加、编辑、删除、和浏览。分页的功能在下篇文章将会实现。
还是BlogController.java文件:
package org.caihaolun.controller;
import org.caihaolun.dao.BlogDAO;
import org.caihaolun.model.Blog;
import org.springframework.stereotype.Controller;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
/*** Created by Administrator on 2017/4/3.* 控制层*/
@Controller
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class BlogController {
private BlogDAO blogDAO;
@Resource
public void setBlogDAO(BlogDAO blogDAO) {
this.blogDAO = blogDAO;
}
private static String textParser(String source) {
if (source == null) {
return "";
}
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < source.length(); i++) {
char c = source.charAt(i);
switch (c) {
case '
buffer.append("<");
break;
case '>':
buffer.append(">");
break;
case '&':
buffer.append("&");
break;
case '"':
buffer.append(""");
break;
case '\n':
buffer.append("
");
break;
default:
buffer.append(c);
}
}
return buffer.toString();
}
@RequestMapping(value = "/addArticle")
@ResponseBody
public Map add(String title, String content, Integer uid) throws Exception {
Map res = new HashMap<>();
Blog blog = new Blog();
blog.setTitle(title);
blog.setContent(textParser(content));
blog.setUserid(uid);
blogDAO.save(blog);
res.put("result", "SUCCESS");
return res;
}
@RequestMapping(value = "/articleList/{uid}")
public String getAllBlog(@PathVariable("uid") Integer uid, ModelMap modelMap) throws Exception {
// 查询表中所有记录 // 将所有记录传递给要返回的jsp页面,放在blogList当中 modelMap.addAttribute("blogList", blogDAO.findByUid(uid));
// 返回原本jsp页面 return "articleList";
}
@RequestMapping(value = "/show/{bid}")
public String get(@PathVariable("bid") Integer bid, ModelMap modelMap) throws Exception {
modelMap.addAttribute("blog", blogDAO.findByID(bid));
return "article";
}
/*** 转到update的目录** @param bid 根据bid返回* @return 页面* @throws Exception*/
@RequestMapping(value = "/update/{bid}")
public String toUpdatePage(@PathVariable("bid") Integer bid, ModelMap modelMap) throws Exception {
modelMap.addAttribute("blog", blogDAO.findByID(bid));
return "articleUpdate";
}
@RequestMapping(value = "/update")
@ResponseBody
public Map update(@RequestBody Blog blog) throws Exception {
Map res = new HashMap<>();
blogDAO.save(blog);
res.put("result", "SUCCESS");
return res;
}
@RequestMapping(value = "/delete/{bid}")
public String delete(@PathVariable("bid") Integer bid) throws Exception {
blogDAO.delete(blogDAO.findByID(bid));
return "index";
}
}
这里我稍微对输入的字符串进行一些处理。html输入的字符需要经过一些转换转为text文本才能存入数据库。否则页面再取会出现各种各样的问题。
接下来就把页面各种功能完善一下:
添加博文的jQuery:
$(document).ready(function () {
$("#pullout").click(function () {
var uid = $.cookie("uid");
var title = $("#title").val();
var text = $("#text").val();
if (title == "" || text == "") {
alert("请确认是否有空缺项!");
} else {
$.post("addArticle", {"title": title, "content": text, "uid": uid},
function (data) {
if (data["result"] == "SUCCESS") {
alert("添加成功!");
$("#myDiv").load("articleList/" + uid);
}
});
}
});
})
列出博文列表:
博文列表
其他模块,都是差不多的写法。就不一一赘述了。
最后的效果:
1、博文列表:
2、添加博文:
3、博文显示:
4、编辑博文:
删除的效果看不到,就不贴了。
就这么多了。私以为,前台和控制层交互的部分最难写,各种各样的路径问题 、ajax传输错误、控制层代码写错,还有前端页面总会出那么几个错,要么js文件执行不了,要么就是少导工具包,总是不能顺畅地写完代码。也许是我前端基础薄弱的一个表征吧。等哪天花点时间得好好看看前端了。