月份:2018年12月

MyBatis插入对象后返回获得自增的主键

很多情况下,我们的主键都是自增的,我们可能在插入后马上就获取到刚刚插入的数据的主键,下面就来记录一下:

插入记录在MyBatis中的写法:

<insert id="saveXxx" parameterType="com.wjy329.entity.xxx">
      <selectKey resultType="Integer" order="AFTER" keyProperty="id">
          SELECT LAST_INSERT_ID()
      </selectKey>
        insert into tableName
		(
			`line2`,
			`line3`
		)
		values
		(
			#{line2},
			#{line3}
		)
</insert>

关键在于

 <selectKey resultType="Integer" order="AFTER" keyProperty="id">
          SELECT LAST_INSERT_ID()
 </selectKey>

你以为仅仅获取到这个就行了?那是不可能的,直接获取返回的int,你会发现是一个固定的数字,它代表刚才插入数据影响的行。

在执行完插入操作后,我们只需在后面直接用getId()方法就行,例如: 

studentDao.saveStudent(student);
Integer id = student.getId;

shell脚本报syntax error: unexpected end of file 错误

在Windows下用Sublime Text编写了脚本,上传到了服务器,然后高高兴兴一执行,出现了syntax error:unexpected end of file错误;在网上查了之后才知道,原来在Windows下写的脚本是dos格式的,而Linux服务器中只能执行unix格式的脚本。

解决方案:

  1.   vi  xxx.sh   用vi编辑脚本(或者vim)

  2. 输入  :set ff   回车,可以查看到当前脚本的格式,如果为fileformat=dos ,则需要修改脚本格式

  3. 输入  :set ff=unix    即可

  4. 再次输入  :set ff  查看脚本格式,如果输出为fileformat=unix,就成功了

  5. 执行脚本,ok

Spring Boot之Kaptcha验证码使用

1.引入Kaptcha依赖

<!-- 验证码 -->
<dependency>
    <groupId>com.github.penggle</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3.2</version>
</dependency>

2.KaptchaBean.java 配置文件

package com.wjy329.shiro.filter;

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.servlet.KaptchaServlet;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class KaptchaBean {
    @Bean
    public org.springframework.boot.web.servlet.ServletRegistrationBean kaptchaServlet() {

        org.springframework.boot.web.servlet.ServletRegistrationBean registrationBean = new org.springframework.boot.web.servlet.ServletRegistrationBean(new KaptchaServlet(), "/kaptcha.jpg");

        registrationBean.addInitParameter(Constants.KAPTCHA_SESSION_CONFIG_KEY,
                Constants.KAPTCHA_SESSION_KEY);
        registrationBean.addInitParameter(Constants.KAPTCHA_IMAGE_HEIGHT, "38");//高度
        registrationBean.addInitParameter(Constants.KAPTCHA_IMAGE_WIDTH, "80");//宽度
        registrationBean.addInitParameter(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "26");//字体大小
        registrationBean.addInitParameter(Constants.KAPTCHA_BORDER_THICKNESS, "1"); //边框
        registrationBean.addInitParameter(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "red"); //文字颜色

        //可以设置很多属性,具体看com.google.code.kaptcha.Constants
//      kaptcha.border  是否有边框  默认为true  我们可以自己设置yes,no
//      kaptcha.border.color   边框颜色   默认为Color.BLACK
//      kaptcha.border.thickness  边框粗细度  默认为1
//      kaptcha.producer.impl   验证码生成器  默认为DefaultKaptcha
//      kaptcha.textproducer.impl   验证码文本生成器  默认为DefaultTextCreator
//      kaptcha.textproducer.char.string   验证码文本字符内容范围  默认为abcde2345678gfynmnpwx
//      kaptcha.textproducer.char.length   验证码文本字符长度  默认为5
//      kaptcha.textproducer.font.names    验证码文本字体样式  默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
//      kaptcha.textproducer.font.size   验证码文本字符大小  默认为40
//      kaptcha.textproducer.font.color  验证码文本字符颜色  默认为Color.BLACK
//      kaptcha.textproducer.char.space  验证码文本字符间距  默认为2
//      kaptcha.noise.impl    验证码噪点生成对象  默认为DefaultNoise
//      kaptcha.noise.color   验证码噪点颜色   默认为Color.BLACK
//      kaptcha.obscurificator.impl   验证码样式引擎  默认为WaterRipple
//      kaptcha.word.impl   验证码文本字符渲染   默认为DefaultWordRenderer
//      kaptcha.background.impl   验证码背景生成器   默认为DefaultBackground
//      kaptcha.background.clear.from   验证码背景颜色渐进   默认为Color.LIGHT_GRAY
//      kaptcha.background.clear.to   验证码背景颜色渐进   默认为Color.WHITE
//      kaptcha.image.width   验证码图片宽度  默认为200
//      kaptcha.image.height  验证码图片高度  默认为50
        return registrationBean;

    }
}

3.前端页面

<div class="layui-form-item">
    <div class="layui-inline">
    <label class="layui-form-label">验证码</label>
    <div class="layui-input-inline">
        <input type="text" name="captcha" required lay-verify="required" placeholder="请输入验证码" autocomplete="off" class="layui-input" style="width: 110px;float: left">
        <img src="kaptcha.jpg" name="captcha"  id="captcha" style="float: right" onclick="refreshCode(this)"/>
    </div>
</div>

这里的 onclick="refreshCode(this)"  是点击刷新验证码;

配置完上面3步可以访问你的页面看看验证码是否显示,如果显示则配置成功,就可以进行后续判断验证码阶段。

image.png

4.判断验证码

我这里由于使用了shiro(其他也一样),我简化了判断的方法,直接在你登陆的控制器内判断即可,Kaptcha会把前端的验证码信息存放到session中,所有我们在登陆的控制器用session中的验证码和前端表单传过来的验证码比较即可;

public String loginUser(@RequestParam("username")String username,
                        @RequestParam("password")String password,
                        @RequestParam("captcha") String captcha,
                        HttpSession httpSession){
    String sessionCaptcha = httpSession.getAttribute("KAPTCHA_SESSION_KEY").toString();
    if(!captcha.equals(sessionCaptcha)){
        return WebUtils.getInstance().writeMsg(ResultCode.ERROR, "验证码输入错误");
    }
    ......
 }

上面是我的验证代码,可以参考一下,注意获取session中的验证码的key为   “KAPTCHA_SESSION_KEY”  

5.点击刷新验证码

前面也说了点击刷新,就是一个方法,需要加入时间更新,代码如下:

function refreshCode(){
    var captcha = document.getElementById("captcha");
    captcha.src = "/kaptcha.jpg?t=" + new Date().getTime();
}

以上就是在项目中添加验证码的方法,希望有所帮助。一些配置项可以查看第2步中的配置类或者百度(-_-)。

Spring Boot之分页

分页是我们 常用的功能,MySQL实现分页的原理 就是用limit,比如 select * from table limit 0,5;  意思就是从0行开始查询5条数据,那么要实现分页我们需要两个参数,起始位置和每页的数据量,起始位置需要计算,为了前端传值的方便,前端只需传入当前页码每页数据量即可,下面我们来具体实现:

数据准备:

-- ----------------------------
-- Table structure for person
-- ----------------------------
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of person
-- ----------------------------
INSERT INTO `person` VALUES ('1', 'wjy', '24');
INSERT INTO `person` VALUES ('2', 'wjy1', '25');
INSERT INTO `person` VALUES ('3', '25', '25');
INSERT INTO `person` VALUES ('4', 'wjy2', '25');
INSERT INTO `person` VALUES ('5', 'wjy3', '25');
INSERT INTO `person` VALUES ('6', 'wjy4', '26');
INSERT INTO `person` VALUES ('7', 'wjy5', '27');
INSERT INTO `person` VALUES ('8', 'wjy0', '24');

image.png

1.分页实体 

PageBean.java:

package com.wjy329.pagedemo.utils;

import java.util.List;

public class PageBean<T> {
    //起始
    private int offset;
    // 当前页
    private int currentPage;
    // 每页显示的数据量
    private int pageCount;
    // 总记录数
    private int totalCount;
    // 总页数 = 总记录数 / 每页显示的行数  (+ 1)
    private int totalPage;
    // 分页查询到的数据
    private List<T> pageData;

    public int getOffset() {
        return offset;
    }

    public void setOffset(int offset) {
        this.offset = offset;
    }

    // 返回总页数
    public int getTotalPage() {
        if (totalCount % pageCount == 0) {
            totalPage = totalCount / pageCount;
        } else {
            totalPage = totalCount / pageCount + 1;
        }
        return totalPage;
    }
    public void setTotalPage(int totalPage) {
        this.totalPage = totalPage;
    }

    public int getCurrentPage() {
        return currentPage;
    }
    public void setCurrentPage(int currentPage){
        this.currentPage = currentPage;
    }
    public int getPageCount() {
        return pageCount;
    }
    public void setPageCount(int pageCount) {
        this.pageCount = pageCount;
    }
    public int getTotalCount() {
        return totalCount;
    }
    public void setTotalCount(int totalCount) {
        this.totalCount = totalCount;
    }

    public List<T> getPageData() {
        return pageData;
    }
    public void setPageData(List<T> pageData) {
        this.pageData = pageData;
    }
}

2.分页工具类

PageUtils.java:

package com.wjy329.pagedemo.utils;

import java.util.List;

public class PageUtils {
    public static PageBean getPage(Integer currentPage, Integer pageCount, Integer total){
        PageBean pageBean = new PageBean();
        //如果传入的当前页面为空,那么默认为第一页
        if(currentPage == null){
            currentPage = 1;
        }
        //如果传入的数据量为空,默认显示5条
        if(pageCount == null){
            pageCount = 5;
        }
        //起始位置的计算
        int offset  = (currentPage-1)*pageCount;
        pageBean.setCurrentPage(currentPage);
        pageBean.setPageCount(pageCount);
        pageBean.setTotalCount(total);
        pageBean.setOffset(offset);

        return pageBean;
    }
}

3.实体类

person.java:

package com.wjy329.pagedemo.entity;


import java.io.Serializable;

public class Person implements Serializable {
    private Integer id;

    private String name;

    private Integer age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

4.PersonMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.wjy329.pagedemo.dao.PersonDao">
    <resultMap id="BaseResultMap" type="com.wjy329.pagedemo.entity.Person">
        <id column="id" jdbcType="INTEGER" property="id" />
        <result column="name" jdbcType="VARCHAR" property="name" />
        <result column="age" jdbcType="INTEGER" property="age" />
    </resultMap>

    <select id="findAllByPage" parameterType="com.wjy329.pagedemo.utils.PageBean" resultMap="BaseResultMap">
        SELECT id,name,age
        FROM person
        LIMIT #{page.offset},#{page.pageCount}
    </select>

    <select id="getAllCnt"  resultType="java.lang.Integer">
    select count(id) from person
  </select>

</mapper>

5.PersonDao.java

package com.wjy329.pagedemo.dao;

import com.wjy329.pagedemo.entity.Person;
import com.wjy329.pagedemo.utils.PageBean;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface PersonDao {
    List<Person> findAllByPage(@Param(value="page")PageBean page);

    Integer getAllCnt();
}

6.PersonService.java

package com.wjy329.pagedemo.service;

import com.wjy329.pagedemo.entity.Person;
import com.wjy329.pagedemo.utils.PageBean;

import java.util.List;

public interface PersonService {
     PageBean queryByPage(Integer currentPage, Integer pageCount);
}

7.PersonServiceImpl.java

package com.wjy329.pagedemo.service.impl;

import com.wjy329.pagedemo.dao.PersonDao;
import com.wjy329.pagedemo.entity.Person;
import com.wjy329.pagedemo.service.PersonService;
import com.wjy329.pagedemo.utils.PageBean;
import com.wjy329.pagedemo.utils.PageUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class PersonServiceImpl implements PersonService {

    @Autowired
    private PersonDao personDao;

    @Override
    public PageBean queryByPage(Integer currentPage,Integer pageCount) {
        Integer total = 0;
        List<Person> persons  = null;
        total = this.personDao.getAllCnt();
        PageBean pageBean = PageUtils.getPage(currentPage,pageCount,total);
        //查询出来的分页数据
        persons = this.personDao.findAllByPage(pageBean);
        pageBean.setPageData(persons);
        return pageBean;
    }
}

8.PersonController.java

package com.wjy329.pagedemo.controller;

import com.wjy329.pagedemo.entity.Person;
import com.wjy329.pagedemo.service.PersonService;
import com.wjy329.pagedemo.utils.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
@RequestMapping("/person")
public class PersonController {
    @Autowired
    private PersonService personService;

    @RequestMapping("/getAll")
    @ResponseBody
    public PageBean getAll(Integer currentPage, Integer pageCount){
        PageBean list = personService.queryByPage(currentPage, pageCount);
        return list;
    }
}

上面就是全部的代码,然后我们开始访问: localhost:80/person/getAll   由于没有传入参数,所以按工具类中的默认 值查询,也就是第一页,5条数据:

image.png

访问: localhost:80/person/getAll?currentPage=2&pageCount=5   返回第2页的5条数据

image.png

上面就是分页的简单实现,然后据需要配合前端 的页面传值和获取 数据等。

demo地址: https://github.com/wjy329/page-demo

JS密码强度判断

 //判断密码规则,长度至少为8位,必须包含大小写字母、数字和特殊符号
 var reg = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}/;
 var result = $("#newPassword").val().match(reg);
 if(result == null){
     Msg.error("密码长度至少为8位,必须包含大小写字母、数字和特殊符号");
     return false;
 }

上面代码是验证密码长度至少为8位,而且必须包含大小写字母、数字和特殊符号。