-
我们现在要实现单击加载出来的某个子项,跳转到相应的detail详情页
- 思路:我们需要获取到所点击书本的id,将id传给控制层
- 我们在控制层使用的是@PathVariable注解来绑定URL中的参数占位符(映射 url 路径中的变量)
前端获取到id之后,路径上需要注意,/xzw没加路径访问不到(没整明白)
-
-
到这里,我们已经实现了详情页的跳转,因为是页面的跳转,我们不要通过ajax,接下来,去编写实现详情页展示的内容
-
跳转缓过来的时候,页面布局不对劲,模板css和js,bootstrap都加载不出,并且图片路径都不对,需要在引入时路劲前面加上/xzw/,
当我们把id传到后台去进行查询的时候,在业务层,参数也传过去了,但是返回值却是null,在这里卡了两个小时,最后发现是实体类没有写注解(@TableName("book"),主键@TableId(type = IdType.AUTO),所以自己一定要注意,现在用的是框架,如果你不写注解,调用BaseMapper里面自带的方法时,是找不到的,所以,切记,切记,,页面上此时加载的全是代码,这是因为数据库的头像图片地址是空的,加上就可以了<link rel="stylesheet" href="/xzw/resources/bootstrap/bootstrap.css"> <link rel="stylesheet" href="/xzw/resources/raty/lib/jquery.raty.css"> <script src="/xzw/resources/jquery.3.3.1.min.js"></script> <script src="/xzw/resources/bootstrap/bootstrap.min.js"></script> <script src="/xzw/resources/raty/lib/jquery.raty.js"></script>
-
在使用星型组件,配置他的初始化图片目录的时候,也需要加上/xzw/
我们是先显示了所有和书本表有关的信息,会员名称还没有显示,那么我们要如何去将会员名称显示出来呢?评论表当中有书本和会员两张表的外键,所以我们可以多加两个对象属性,但是我们让他在自动加载SQL的时候不自动生成
@TableField(exist = false)//表示表中不存在对应字段,不会参与到SQL的自动生成
private Book book;//这个对象需要我们自己手动查询得到
@TableField(exist = false)//表示表中不存在对应字段,不会参与到SQL的自动生成
private Member member;//这个对象需要我们自己手动查询得到
但是当我在写member类的时候,由于大意修改,没有将属性名nickname和他对应的get,set方法的方法名写成一致的,导致报了错,找了很久,所以这里要注意
然后,我们在评价业务层当中,需要根据评论集合当中的单个评论对应的会员id去查对应会员的属性,然后再去给刚刚定义好的member会员对象属性初始化,所以需要用到遍历。
@Override
public List<Evaluation> getEvaluationByBookId(Long bookId) {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("book_id",bookId);
queryWrapper.eq("state","enable");
queryWrapper.orderByDesc("create_time");
List<Evaluation> evaluationList = evaluationMapper.selectList(queryWrapper);
Book book = bookMapper.selectById(bookId);
for (Evaluation evaluation : evaluationList) {
Member member = memberMapper.selectById(evaluation.getMemberId());
evaluation.setMember(member);
evaluation.setBook(book);
}
return evaluationList;
}
这一步完成之后,我们需要在控制层通过modelandview对象,将初始化的评论list加到session当中,后续在页面中,通过freemarker模板中的循环遍历显示所有的评论
//单击某本书,跳转到详情
// 根据图书id,拿到所有评论
@GetMapping("/book/{bookId}")
public ModelAndView displayBookDetail(@PathVariable("bookId")Long bookId){
ModelAndView mav = new ModelAndView("/detail");
Book book = bookService.getBookById(bookId);
List<Evaluation> evaluationList = evaluationService.getEvaluationByBookId(bookId);
mav.addObject("book",book);
mav.addObject("evaluationList",evaluationList);
return mav;
}
这样详情及评论效果就实现了
验证码功能的实现
- 导入的依赖
-
<!--验证码--> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency>
-
- 在applicationContext.xml里面配置kaptcha:验证码的宽度,高度,字符等
-
<!--配置 kaptcha--> <bean id="defaultKaptcha" class="com.google.code.kaptcha.impl.DefaultKaptcha"> <property name="config"> <bean class="com.google.code.kaptcha.util.Config"> <constructor-arg> <props> <prop key="kaptcha.border">no</prop><!--边框--> <prop key="kaptcha.image.width">120</prop><!--宽度120px--> <prop key="kaptcha.textproducer.font.color">blue</prop><!--color--> <prop key="kaptcha.textproducer.font.size">40</prop><!--字大小--> <prop key="kaptcha.textproducer.char.length">4</prop><!--几个字符--> </props> </constructor-arg> </bean> </property> </bean>
-
- 然后需要写一个专门用来生成验证码的Controller,需要用的时候,直接拿来用就行,不需要自己会写,
-
@Controller public class KaptchaController { @Autowired private Producer defaultKaptcha;//这个名字要和主配置文件里面的相同<bean id="defaultKaptcha" @GetMapping("verify_code") public void createVerifycode(HttpServletRequest request, HttpServletResponse response)throws Exception{ response.setDateHeader("Expires",0); //响应立即过期 //不缓存任何图片 response.setHeader("Cache-Control","no-store,no-cache,must-revalidate"); response.setHeader("Cache-Control","post-check=0,pre-check=0"); response.setHeader("Pragma","no-cache"); response.setContentType("image/png"); //生成验证码文本 String verifyCode=defaultKaptcha.createText(); request.getSession().setAttribute("verifyCode",verifyCode); System.out.println(request.getSession().getAttribute("verifyCode")); //转图片 BufferedImage image = defaultKaptcha.createImage(verifyCode);//创建验证码图片 ServletOutputStream outputStream = response.getOutputStream(); //ImageIO.setUseCache(false); 有的不加此,会报错 ImageIO.write(image,"png",outputStream);//输出图片流 outputStream.flush(); outputStream.close(); } }
-
-
效果如图