ssm(springmvc4+spring4+mybatis3)整合实战-个人博客系统-前端首页的开发
前面介绍完了util包的各种工具类、service层、model层以及dao层的实现,可以说是分享了一大半了!可能有些博友对于其中的code的作用不是很知晓,但是我相信随着我controller以及页面的开发分享,我想,你会逐渐知晓前面介绍的作用的。特别是比较实用的各种工具类:比如日期处理、加密解密、web文件如图片等的处理、文件下载等等、分页工具类、异步或者同步response工具类等等。
本篇博文将介绍介绍前端页面的开发。主要有首页的列表展示、首页分页与分类查询、首页数据的全文检索查询、博客详情、博客评论以及源代码或者叫文件下载
1、首页请求/index可以得到首页,请求/downloadFile可以得到本博客系统的源码压缩包,控制器代码IndexController.java,其中首页博客列表展示时采用了缩略图的形式:这里面采用的技术是jsoup,去检索出博客内容中前三张图片,进行展示
package com.steadyjack.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.steadyjack.entity.Blog;
import com.steadyjack.entity.PageBean;
import com.steadyjack.service.BlogService;
import com.steadyjack.util.PageUtil;
import com.steadyjack.util.StringUtil;
import com.steadyjack.util.WebFileUtil;
/**
* title:IndexController.java
* description:前端主页Controller
* time:2017年1月21日 下午10:28:50
* author:debug-steadyjack
*/
@Controller
public class IndexController {
@Resource
private BlogService blogService;
@RequestMapping("/")
public String defaultPage(){
return "redirect:/index";
}
/**
* title:IndexController.java
* description:请求主页
* time:2017年1月21日 下午10:30:17
* author:debug-steadyjack
* @param page
* @param typeId
* @param releaseDateStr
* @param request
* @return
* @throws Exception
*/
@RequestMapping("/index")
public ModelAndView index(@RequestParam(value="page",required=false)String page,
@RequestParam(value="typeId",required=false)String typeId,
@RequestParam(value="releaseDateStr",required=false)String releaseDateStr,
HttpServletRequest request)throws Exception{
ModelAndView mav=new ModelAndView();
if(StringUtil.isEmpty(page)){
page="1";
}
Integer pageNo=Integer.parseInt(page);
PageBean pageBean=new PageBean(pageNo,10);
Map map=new HashMap();
map.put("start", pageBean.getStart());
map.put("size", pageBean.getPageSize());
map.put("typeId", typeId);
map.put("releaseDateStr", releaseDateStr);
List blogList=blogService.list(map);
for(Blog blog:blogList){
//用于存放博客内容里面的图片,从而生成缩略图-用于前端页面展示
List imagesList=blog.getImagesList();
String blogInfo=blog.getContent();
Document doc=Jsoup.parse(blogInfo);
//查找扩展名是jpg的图片:根据页面需要拿n张图片,这里拿了3张
Elements jpgs=doc.select("img[src$=.jpg]");
if (jpgs!=null && jpgs.size()>0) {
for(int i=0;i
其实,这个控制器controller就已经展示了springmvc的角色,彻底对springmvc的工作原理进行淋漓尽致的应用。看过springmvc的宏观工作原理的博友都知道,springmvc的工作原理大概是这样的:
1、客户端发出一个http请求给web服务器,web服务器对http请求进行解析,如果匹配DispatcherServlet的请求映射路径(在web.xml中指定),web容器将请求转交给DispatcherServlet.
2、DipatcherServlet接收到这个请求之后将根据请求的信息(包括URL、Http方法、请求报文头和请求参数Cookie等)以及HandlerMapping的配置找到处理请求的处理器(Handler)。
3、DispatcherServlet根据HandlerMapping找到对应的Handler,将处理权交给Handler(Handler将具体的处理进行封装),再由具体的HandlerAdapter对Handler进行具体的调用。
4、Handler对数据处理完成以后将返回一个ModelAndView()对象给DispatcherServlet。
5、Handler返回的ModelAndView()只是一个逻辑视图并不是一个正式的视图,DispatcherSevlet通过ViewResolver将逻辑视图转化为真正的视图View。
6、Dispatcher通过model解析出ModelAndView()中的参数进行解析最终展现出完整的view并返回给客户端
比如对于请求参数的写法,可以用参数封装(当然啦,这个可能不是spring4.x的功能),controller返回的一般是String,即一个视图的地址等等。
对于springmvc的详细介绍可以另外看多几篇博客。
2、完了之后,介绍一下博客详情、博客的全文检索模糊查询(这里采用lucene实现)以及博客的分页(在这里采用 同步刷新)logController.java以及评论控制器CommentController.java:
package com.steadyjack.controller;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import com.steadyjack.entity.Blog;
import com.steadyjack.lucene.BlogIndex;
import com.steadyjack.service.BlogService;
import com.steadyjack.service.CommentService;
import com.steadyjack.util.StringUtil;
/**
* title:BlogController.java
* description:前端博客Controller层
* time:2017年1月17日 下午9:44:19
* author:debug-steadyjack
*/
@Controller
@RequestMapping("/blog")
public class BlogController {
@Resource
private BlogService blogService;
@Resource
private CommentService commentService;
// 博客索引
private BlogIndex blogIndex=new BlogIndex();
/**
* title:BlogController.java
* description:博客详细信息
* time:2017年1月17日 下午9:51:50
* author:debug-steadyjack
* @param id
* @param request
* @throws Exception
*/
@RequestMapping("/articles/{id}")
public ModelAndView details(@PathVariable Integer id,HttpServletRequest request)throws Exception{
ModelAndView modelAndView=new ModelAndView();
Blog blog=blogService.findById(id);
String keyWords=blog.getKeyWord();
if(StringUtil.isNotEmpty(keyWords)){
String arr[]=keyWords.split(" ");
modelAndView.addObject("keyWords",StringUtil.filterWhite(Arrays.asList(arr)));
}else{
modelAndView.addObject("keyWords",null);
}
modelAndView.addObject("blog", blog);
Integer clickHit=blog.getClickHit();
clickHit = clickHit==null?0:clickHit+1;
//博客点击次数加1
blog.setClickHit(clickHit);
blogService.update(blog);
Map map=new HashMap();
//查询审核通过的评论
map.put("blogId", blog.getId());
map.put("state", 1);
//System.out.println(request.getServletContext().getContextPath());
modelAndView.addObject("commentList", commentService.list(map));
modelAndView.addObject("pageCode", this.genUpAndDownPageCode(blogService.getLastBlog(id),blogService.getNextBlog(id),request.getServletContext().getContextPath()));
modelAndView.addObject("mainPage", "foreground/blog/view.jsp");
modelAndView.addObject("pageTitle",blog.getTitle());
modelAndView.setViewName("mainTemp");
//查询审核通过的评论
return modelAndView;
}
/**
* title:BlogController.java
* description:根据查询信息查询相关博客信息
* time:2017年1月17日 下午11:11:29
* author:debug-steadyjack
* @param q
* @param page
* @param request
* @return ModelAndView
* @throws Exception
*/
@RequestMapping("/q")
public ModelAndView search(@RequestParam(value="q",required=false)String q,@RequestParam(value="page",required=false)String page,HttpServletRequest request)throws Exception{
if(StringUtil.isEmpty(page)){
page="1";
}
ModelAndView mav=new ModelAndView();
mav.addObject("mainPage", "foreground/blog/result.jsp");
blogIndex.setRequest(request);
List blogList=blogIndex.searchBlog(q.trim());
Integer pageNo=Integer.parseInt(page);
Integer pageSize=10;
Integer toIndex=blogList.size()>=pageNo*pageSize?pageNo*pageSize:blogList.size();
//list的subList是分页的一种:返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图
mav.addObject("blogList",blogList.subList((pageNo-1)*pageSize, toIndex));
mav.addObject("pageCode",this.genUpAndDownPageCode(pageNo, blogList.size(), q,10,request.getServletContext().getContextPath()));
mav.addObject("q",q);
mav.addObject("resultTotal",blogList.size());
mav.addObject("pageTitle","搜索关键字'"+q+"'结果页面_Java修炼之博客系统");
mav.setViewName("mainTemp");
return mav;
}
/**
* title:BlogController.java
* description: 获取下一篇博客和下一篇博客
* time:2017年1月17日 下午10:14:03
* author:debug-steadyjack
* @param lastBlog
* @param nextBlog
* @param projectContext
* @return String
*/
private String genUpAndDownPageCode(Blog lastBlog,Blog nextBlog,String projectContext){
StringBuffer pageCode=new StringBuffer();
if(lastBlog==null || lastBlog.getId()==null){
pageCode.append("上一篇:没有了
");
}else{
pageCode.append("");
}
if(nextBlog==null || nextBlog.getId()==null){
pageCode.append("下一篇:没有了
");
}else{
pageCode.append("");
}
return pageCode.toString();
}
/**
* 获取上一页,下一页代码 查询博客用到(简单的分页)
* @param page 当前页
* @param totalNum 总记录数
* @param q 查询关键字
* @param pageSize 每页大小
* @param projectContext
* @return
*/
private String genUpAndDownPageCode(Integer page,Integer totalNum,String q,Integer pageSize,String projectContext){
long totalPage=totalNum%pageSize==0?totalNum/pageSize:totalNum/pageSize+1;
StringBuffer pageCode=new StringBuffer();
if(totalPage==0){
return "";
}else{
pageCode.append("");
}
return pageCode.toString();
}
}
package com.steadyjack.controller;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.steadyjack.entity.Blog;
import com.steadyjack.entity.Comment;
import com.steadyjack.service.BlogService;
import com.steadyjack.service.CommentService;
import com.steadyjack.util.ResponseUtil;
/**
* 评论Controller层
* @author Administrator
*
*/
@Controller
@RequestMapping("/comment")
public class CommentController {
@Resource
private CommentService commentService;
@Resource
private BlogService blogService;
/**
* title:CommentController.java
* description:添加或者修改评论
* time:2017年1月23日 下午8:02:05
* author:debug-steadyjack
* @param comment
* @param imageCode
* @param request
* @param response
* @param session
* @return
* @throws Exception
*/
@RequestMapping("/save")
public String save(Comment comment,@RequestParam("imageCode") String imageCode,
HttpServletRequest request,HttpServletResponse response,HttpSession session)throws Exception{
//获取系统生成的验证码
String sRand=(String) session.getAttribute("sRand");
JSONObject result=new JSONObject();
//操作的记录条数
int resultTotal=0;
if(!imageCode.equals(sRand)){
result.put("success", false);
result.put("errorInfo", "验证码填写错误!");
}else{
//获取用户IP
String userIp=request.getRemoteAddr();
comment.setUserIp(userIp);
if(comment.getId()==null){
resultTotal=commentService.add(comment);
//该博客的回复次数加1
Blog blog=blogService.findById(comment.getBlog().getId());
blog.setReplyHit(blog.getReplyHit()+1);
blogService.update(blog);
}else{
}
if(resultTotal>0){
result.put("success", true);
}else{
result.put("success", false);
}
}
ResponseUtil.write(response, result);
return null;
}
}
package com.steadyjack.controller;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.steadyjack.entity.Blogger;
import com.steadyjack.service.BloggerService;
import com.steadyjack.util.CryptographyUtil;
/**
* title:BloggerController.java
* description:博主Controller层
* time:2017年1月23日 下午10:01:10
* author:debug-steadyjack
*/
@Controller
@RequestMapping("/blogger")
public class BloggerController {
@Resource
private BloggerService bloggerService;
/**
* title:BloggerController.java
* description:用户登录
* time:2017年1月23日 下午10:01:20
* author:debug-steadyjack
* @param blogger
* @param request
* @return
*/
@RequestMapping("/login")
public String login(Blogger blogger,HttpServletRequest request){
Subject subject=SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(blogger.getUserName(), CryptographyUtil.md5(blogger.getPassword(), "debug"));
try{
//登录验证
subject.login(token);
return "redirect:/admin/main.jsp";
}catch(Exception e){
e.printStackTrace();
request.setAttribute("blogger", blogger);
request.setAttribute("errorInfo", "用户名或密码错误!");
return "login";
}
}
/**
* title:BloggerController.java
* description:查找博主信息
* time:2017年1月23日 下午10:12:45
* author:debug-steadyjack
* @return
* @throws Exception
*/
@RequestMapping("/aboutMe")
public ModelAndView aboutMe()throws Exception{
ModelAndView mav=new ModelAndView();
mav.addObject("blogger",bloggerService.find());
mav.addObject("mainPage", "foreground/blogger/info.jsp");
mav.addObject("pageTitle","关于博主_Java开源博客系统");
mav.setViewName("mainTemp");
return mav;
}
}
package com.steadyjack.realm;
import javax.annotation.Resource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import com.steadyjack.entity.Blogger;
import com.steadyjack.service.BloggerService;
/**
* title:MyRealm.java
* description:自定义Realm(域)
* time:2017年1月22日 下午10:50:57
* author:debug-steadyjack
*/
public class MyRealm extends AuthorizingRealm{
@Resource
private BloggerService bloggerService;
/**
* 为当限前登录的用户授予角色和权
* (由于目前系统没有啥资源且只有admin超级用户,故而没写授予角色、权限(资源)逻辑)
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
/**
* 验证当前登录的用户
* (成功时,将登陆用户绑定到会话中;失败时,其实会报各种exception,理当抛出用于前端页面展示(后期实现))
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取身份(在这里指 用户名)-凭证(在这里指 密码)
String userName=(String)token.getPrincipal();
Blogger blogger=bloggerService.getByUserName(userName);
if(blogger!=null){
//当前用户信息存到session中
SecurityUtils.getSubject().getSession().setAttribute("currentUser", blogger);
AuthenticationInfo authcInfo=new SimpleAuthenticationInfo(blogger.getUserName(),blogger.getPassword(),getName());
return authcInfo;
}else{
return null;
}
}
}
最后,把WebContent下的页面分享出来:前端用的是bootstrap,后端页面用的是easyui,目录如图:
页面以及样式来这里下载:
如果有相关问题:如想找我付费开发其他功能,讨论其中相关问题等等,可以来以下两群找我,我叫debug!
Java开源技术交流:583522159 鏖战八方群:391619659