SSM+Cron+Javamail定时发送邮件(纯代码参考)

依赖导入

<?xml version="1.0" encoding="UTF-8"?>

< project xmlns=“http://maven.apache.org/POM/4.0.0”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
< modelVersion>4.0.0< /modelVersion>

<groupId>com.qf</groupId>
<artifactId>day06-ssm</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<!--声明版本号-->
<properties>
    <spring.version>4.3.8.RELEASE</spring.version>
</properties>
<dependencies>
    <!--1. mybatis.-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>
    <!--2. mysql驱动.-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.38</version>
    </dependency>
    <!--3. druid连接池.-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.10</version>
    </dependency>
    <!--4. lombok.-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.20</version>
    </dependency>
    <!--5. mybatis-spring.-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.2</version>
    </dependency>
    <!--6. spring的核心依赖.-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!--7. spring的aspects.-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!--8. spring的jdbc.-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!--9. spring的test.-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!--10. junit.-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <!--11. log4j-->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <!--12. spring的webmvc.-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!--13. servlet全家桶.-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>javax.servlet.jsp-api</artifactId>
        <version>2.3.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    <!--jackson依赖,用于处理json数据-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.8</version>
    </dependency>
    <!--云片短信平台SDK工具-->
    <dependency>
        <groupId>com.yunpian.sdk</groupId>
        <artifactId>yunpian-java-sdk</artifactId>
        <version>1.2.7</version>
    </dependency>
    <!--hibernate-validator校验-->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.4.1.Final</version>
    </dependency>
    <!--shiro    ,只用MD5加密功能-->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.4.0</version>
    </dependency>
    <!--上传图片需要的两个依赖-->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>
	<!--commons-lang3 工具类-->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.4</version>
    </dependency>
    <!-- shiro整合spring全家桶-->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.4.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-web</artifactId>
        <version>1.4.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.4.0</version>
    </dependency>
	<!--quartz定时任务-->
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.3.0</version>
    </dependency>
	<!-- spring的支持包.-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>
	<!-- javamail-->
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>mail</artifactId>
        <version>1.4</version>
    </dependency>
</dependencies>
</project>

配置文件

目录结构

main->java|resources->mapper,applicaitonContext-dao.xml,application-service.xml,applicationContext-task.xml,database.properties,env.properties,log4j.properties,mybatis-config.xml,spring-shiro.xml,springmvc.xml
main->webapp->static|WEB-INF->jsp->web.xml

applicationContext-dao.xml

<?xml version="1.0" encoding="UTF-8"?>

< beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
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/context http://www.springframework.org/schema/context/spring-context.xsd”>

<!--1. 加载properties文件-->
<context:property-placeholder location="classpath:database.properties" />

<!--2. 创建数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" >
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>

<!--3. 创建 SqlSessionFactoryBean-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
    <!--1. 注入数据源-->
    <property name="dataSource" ref="dataSource" />
    <!--2. 加载mybatis核心配置文件-->
    <property name="configLocation" value="classpath:mybatis-config.xml" />
    <!--3. 扫描映射文件-->
    <property name="mapperLocations" value="classpath:mapper/*.xml" />
    <!--4. 配置别名-->
    <property name="typeAliasesPackage" value="com.qf.pojo" />
</bean>

<!--4. 通过MapperScannerConfigurer扫描mapper接口-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!--指定扫描的包-->
    <property name="basePackage" value="com.qf.mapper" />
</bean>
</beans>

applicationContext-service.xml

<?xml version="1.0" encoding="UTF-8"?>

< beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance” xmlns:tx=“http://www.springframework.org/schema/tx”
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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd”>

<!--开启IOC/DI的注解扫描-->
<context:component-scan base-package="com.qf.service.impl" />

<!--声明式事务-->
<!--1. 数据源事务管理器.-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入dataSource-->
    <property name="dataSource" ref="dataSource" />
</bean>
<!--2. 开启事务注解扫描.-->
<tx:annotation-driven transaction-manager="transactionManager" />

< /beans>

applicaitonContext-task.xml

<?xml version="1.0" encoding="UTF-8"?>

< beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd”>

<bean class="com.qf.quartz.SendMailUtil" />

<!--    1. 具体任务-->
<bean id="heiheihei" class="com.qf.quartz.MyJobDetail" />	

<!--    2. 将任务设置到MethodInvokingJobDetailFactoryBean.-->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!--   1. 设置任务所在的类.-->
    <property name="targetObject" ref="heiheihei" />
<!--   2. 设置类中的方法作为任务.-->
    <property name="targetMethod" value="say" />
</bean>
<!--    3. 指定这个任务的执行周期 CronTriggerFactoryBean-->
<bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!--    1. 将任务描述设置进来.-->
<property name="jobDetail" ref="jobDetail" />
<!--    2. 配置cron表达式指定任务的执行周期  从0秒开始,没3秒执行一次.  -->
    <property name="cronExpression" value="0/3 * * ? * *" />
</bean>

<!--    1. 创建发送邮件实例-->
<bean id="sendBirthdayMail" class="com.qf.quartz.SendMailTask" />
<!--    2. 配置到methodInvokingJob....-->
<bean id="sendBirthdayMailJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="sendBirthdayMail" />
    <property name="targetMethod" value="sendBirthdayMail" />
</bean>
<!--    3. 配置到cronTrigger...-->
<bean id="sendBirthdayMailTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref="sendBirthdayMailJobDetail" />
    <property name="cronExpression" value="30 15 17 * * ?" />
</bean>

<!--    4. 将指定好周期的任务配置到课程表中  SchedulerFactoryBean-->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<!--        设置trigger-->
    <property name="triggers">
        <array>
            <ref bean="trigger" />
            <ref bean="sendBirthdayMailTrigger" />
        </array>
    </property>
</bean>

< /beans>

database.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///ssm?characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root

env.properties

apikey=bf4463a129d359b07d20130026da2d30
pic_types=jpg,png,gif

log4j.properties

log4j.rootLogger=ERROR,A1
log4j.logger.org.mybatis = DEBUG
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n

mybatis.xml

<?xml version="1.0" encoding="UTF-8" ?>

< !DOCTYPE configuration
PUBLIC “-//mybatis.org//DTD Config 3.0//EN”
“http://mybatis.org/dtd/mybatis-3-config.dtd”>
< configuration>

<settings>
    <!-- 开启驼峰映射 -->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

<!--<typeAliases>-->
    <!--<package name="com.qf.pojo" />-->
<!--</typeAliases>-->

< /configuration>

spring-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>

< beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
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/context http://www.springframework.org/schema/context/spring-context.xsd”>

<!--    开启realm的注解扫描-->
<context:component-scan base-package="com.qf.realm" />

<!--    安全管理器.-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--        注入realm-->
    <property name="realm" ref="customRealm" />
</bean>

<!--    id为shiroFilter的实例.ShiroFilterFactoryBean-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!--        注入安全管理器-->
    <property name="securityManager" ref="securityManager" />
<!--        设置登录页面路径-->
    <property name="loginUrl" value="/login.html" />
<!--        没有权限时,跳转的页面-->
    <property name="unauthorizedUrl" value="/401.html" />
<!--        配置过滤器链-->
    <property name="filterChainDefinitions" >
        <value>
            /user/* = anon
            /static/* = anon
            /* = authc
        </value>
    </property>
</bean>

< /beans>

springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>

< beans xmlns=“http://www.springframework.org/schema/beans”
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”>

<!--加载env.properties文件-->
<context:property-placeholder location="classpath:env.properties" />

<!--开启注解扫描-->
<context:component-scan base-package="com.qf.controller,com.qf.util,com.qf.handler" />
<!--mvc注解驱动-->
<mvc:annotation-driven />
<!--视图解析器
        /WEB-INF/jsp/user/register.jsp
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>

<!--基于tomcat对静态资源放行-->
<!-- 基于服务器的方式 -->
<mvc:default-servlet-handler />

<!--基于springmvc手动放行-->
<!--    <mvc:resources mapping="/static/**" location="/static/" />-->

<!--    配置文件上传项-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--        <property name="maxUploadSize" value="5242880" />-->
</bean>

<!--    拦截器 -->
<!--    <mvc:interceptors>-->
<!--        <mvc:interceptor>-->
<!--            <mvc:mapping path="/**" />-->
<!--            <mvc:exclude-mapping path="/user/**"/>-->
<!--            <bean class="com.qf.interceptor.AuthenticationInterceptor" />-->
<!--        </mvc:interceptor>-->
<!--    </mvc:interceptors>-->

< /beans>

webapp->WEB-INF->web.xml

<?xml version="1.0" encoding="UTF-8"?>

< web-app xmlns=“http://xmlns.jcp.org/xml/ns/javaee”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd”
version=“3.1”>

<!--    shiro整合spring的过滤器-->
   <!-- <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>-->

<!--    处理404-->
<error-page>
    <error-code>404</error-code>
    <location>/form.jsp</location>
</error-page>

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/static/*</url-pattern>
</servlet-mapping>

<!--2. 处理post请求中文乱码-->
<filter>
    <filter-name>characterEncoding</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>characterEncoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!--    处理RESTful的put|delete|patch请求-->
<filter>
    <filter-name>hiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>hiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<!--1. 前端控制器-->
<servlet>
    <servlet-name>springMvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>springMvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<!--3. spring提供的监听器,在项目初始化时,加载applicationContext-*.xml-->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext-*.xml</param-value>
</context-param>
<!--    ,classpath:spring-shiro.xml-->

< /web-app>

Test方法

AcTest文件

package com.qf;

import com.yunpian.sdk.YunpianClient;
import com.yunpian.sdk.model.Result;
import com.yunpian.sdk.model.SmsSingleSend;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.Map;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
“classpath:applicationContext-dao.xml”,
“classpath:applicationContext-service.xml”
})
public class AcTests {
@Test
public void sendSMS(){
}
}

UserMapperTest

package com.qf.mapper;

import com.qf.AcTests;
import com.qf.pojo.User;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.Set;

import static org.junit.Assert.*;

public class UserMapperTest extends AcTests {

@Autowired
private UserMapper userMapper;

@Test
public void findCountByUsername() {
    Integer count = userMapper.findCountByUsername("admin123");
    System.err.println(count);
}

@Test
@Transactional
public void save(){
    User user = new User();
    user.setUsername("xxxxx");
    user.setPassword("xxxxx");
    user.setPhone("11111111111");
    Integer count = userMapper.save(user);
    assertEquals(new Integer(1),count);
}

@Test
public void findByUsername(){
    User user = userMapper.findByUsername("admin");
    System.err.println(user);
}

@Test
public void findTodayPassBirthdayUser(){
    Set<User> userList = userMapper.findTodayPassBirthdayUser();
    for (User user : userList) {
        System.err.println(user);
    }
}

}

UserServiceTest

package com.qf.service;

import com.qf.AcTests;
import com.qf.pojo.User;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.Set;

import static org.junit.Assert.*;

public class UserServiceTest extends AcTests {

@Autowired
private UserService userService;

@Test
public void checkUsername() {
    Integer count = userService.checkUsername("admin");
    System.out.println(count);
}

@Test
@Transactional
public void register(){
    User user = new User();
    user.setUsername("xxxxx");
    user.setPassword("xxxxx");
    user.setPhone("11111111111");
    Integer count = userService.register(user);
    assertEquals(new Integer(1),count);
}

@Test
public void login(){
    User user = userService.login("admin", "admin");
    System.out.println(new Md5Hash("admin",null,1024).toString());
    System.err.println(user);
}

@Test
public void findToday(){
    Set<User> userList = userService.findTodayPassBirthdayUser();
    System.out.println(userList);
}

}

com.qf.SsmConstant

package com.qf.constant;

public interface SsmConstant {

/** 重定向 */
String REDIRECT = "redirect:";

/** 放在session域中验证码的key. */
String CODE = "code";

/** 放在session域中的用户信息 */
String USER = "user";

/** 跳转到注册页面的路径 */
String REGISTER_UI = "/user/register-ui";

/** 跳转到登录页面的路径 */
String LOGIN_UI = "/user/login-ui";

/** 跳转到添加页面 */
String ITEM_ADD_UI = "/item/add-ui";

}

com.qf.controller.ItemController

package com.qf.controller;

import static com.qf.constant.SsmConstant.;
import com.qf.pojo.Item;
import com.qf.service.ItemService;
import com.qf.util.PageInfo;
import com.qf.vo.ResultVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.
;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Controller
@RequestMapping("/item")
public class ItemController {

@Autowired
private ItemService itemService;

// 商品的首页
/**
 * 2. controller接收三个参数.
*             name,非必传项.
*             page,非必传项,设置一个默认值,默认值为1.
*             size,非必传项,设置一个默认值,默认值为5.
 * @param name
 * @param page
 * @param size
 * @return
 */
@GetMapping("/list")
public String list(String name,
                   @RequestParam(value = "page",defaultValue = "1")Integer page,
                   @RequestParam(value = "size",defaultValue = "5")Integer size,
                   Model model){
    //1. 调用service查询数据
    PageInfo<Item> pageInfo = itemService.findItemByNameLikeAndLimit(name,page,size);
    //2. controller将pageInfo放到request域中,将接收到的商品名称name也放到request域中.
    model.addAttribute("pageInfo",pageInfo);
    model.addAttribute("name",name);

    //3. 转发页面
    return "item/item_list";
}

// 跳转到添加商品页面
// /item/add-ui
@GetMapping("/add-ui")
public String  addUI(String addInfo,Model model){
    model.addAttribute("addInfo",addInfo);
    return "item/item_add";
}

@Value("${pic_types}")
public String picType;

// 添加商品信息.
//    Request URL: http://localhost/item/add
//    Request Method: POST
@PostMapping("/add")
public String add(@Valid Item item, BindingResult bindingResult,
                  RedirectAttributes redirectAttributes,
                  MultipartFile picFile, HttpServletRequest req) throws IOException {
    //=========================校验参数======================================
    //===============================================================
    if(bindingResult.hasErrors()){
        // 获得具体信息
        String msg = bindingResult.getFieldError().getDefaultMessage();
//           参数不合法
        redirectAttributes.addAttribute("addInfo",msg);
        return REDIRECT + ITEM_ADD_UI;
    }



    //========================图片上传=======================================
    //===============================================================
//        1. 对图片的大小做校验.  要求图片小于5M.   5242880
    long size = picFile.getSize();
    if(size > 5242880L){
//          图片过大
        redirectAttributes.addAttribute("addInfo","图片过大,要求小于5M");
        return REDIRECT + ITEM_ADD_UI;
    }
    boolean flag = false;
//        2. 对图片的类型做校验.   jpg.   png.   gif.
    String[] types = picType.split(",");
    for (String type : types) {
        if(StringUtils.endsWithIgnoreCase(picFile.getOriginalFilename(),type)){
            // 图片类型正确.
            flag = true;
            break;
        }
    }
    if(!flag){
//           图片类型不正确
        redirectAttributes.addAttribute("addInfo","图片类型不正确,要求" + picType);
        return REDIRECT + ITEM_ADD_UI;
    }
//        3. 校验图片是否损坏.
    BufferedImage image = ImageIO.read(picFile.getInputStream());
    if(image == null){
//          图片已经损坏
        redirectAttributes.addAttribute("addInfo","图片已经损坏");
        return REDIRECT + ITEM_ADD_UI;
    }
    //===========================将图片保存到本地===fastDFS=========================================
    //1. 给图片起一个新名字
    String prefix = UUID.randomUUID().toString();
    String suffix = StringUtils.substringAfterLast(picFile.getOriginalFilename(),".");
    String newName = prefix + "." + suffix;
    //2. 将图片保存到本地
    String path = req.getServletContext().getRealPath("") + "\\static\\img\\" + newName;
    File file = new File(path);
    // 健壮性判断.
    if(!file.getParentFile().exists()){
        file.getParentFile().mkdirs();
    }
    picFile.transferTo(file);
    //3. 封装图片的访问路径.
    String pic = "http://localhost/static/img/" + newName;



    //====================================保存商品信息==================================================================
    //======================================================================================================
    item.setPic(pic);

    // 调用service保存商品信息.
    Integer count = itemService.save(item);
    // 判断count
    if(count == 1) {
        return REDIRECT + "/item/list";
    }else{
//          添加商品信息失败
        redirectAttributes.addAttribute("addInfo","添加商品信息失败!");
        return REDIRECT + ITEM_ADD_UI;
    }
}


// 根据id删除商品信息.
//    Request URL: http://localhost/item/del/14
//    Request Method: DELETE
@DeleteMapping("/del/{id}")
@ResponseBody
public ResultVO del(@PathVariable Long id){
    //1. 调用service删除商品
    Integer count = itemService.del(id);
    //2. 根据结果给页面响应json
    if(count == 1){
        // 删除成功
        return new ResultVO(0,"成功",null);
    }else{
        return new ResultVO(88,"删除商品失败",null);
    }
}

}

com.qf.UserController

package com.qf.controller;

import static com.qf.constant.SsmConstant.;
import com.qf.pojo.User;
import com.qf.service.UserService;
import com.qf.util.SendSMSUtil;
import com.qf.vo.ResultVO;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.
;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/user")
public class UserController {

@Autowired
private UserService userService;

// 发短信工具类.
@Autowired
private SendSMSUtil sendSMSUtil;


// 跳转到注册页面
@GetMapping("/register-ui")
public String registerUI(){
    // 转发到注册页面.
    return "user/register";
}

//    Request URL: http://localhost/user/check-username
//    Request Method: POST
//    {"username":"admin"}   <json>
//1. json数据需要反序列化成pojo对象.
// jsonlib              比较古老的json工具.        第三方依赖过多.        当POJO类过于复杂时,序列化可能会出现问题.
// jackson              spring默认使用的工具.      三个依赖.              当POJO类过于复杂时,序列化可能会出现问题.
// gson                 google的json工具.          一个依赖.
// jackson和gson和spring framework可以0配置整合.
// fastJSON             阿里巴巴的json工具.        一个依赖.              当POJO类过于复杂时,序列化可能会出现问题.
// fastJSON号称自己是最快的json工具.

// 页面发送json数据时,接收的数据类型 ->   map,pojo类.
@PostMapping("/check-username")
@ResponseBody       // 不走视图解析器,直接响应.   如果返回结果为Map/pojo类,自动序列化成json.
public ResultVO checkUsername(@RequestBody User user){
    //1. 调用service,判断用户名是否可用.
    Integer count = userService.checkUsername(user.getUsername());

    //2. 使用ResultVO响应数据
    return new ResultVO(0,"成功",count);
    /*
    使用Map响应
    //2. 封装响应数据的Map
    Map<String,Object> result = new HashMap<>();
    result.put("code",0);
    result.put("msg","成功");
    result.put("data",count);

    //3. 返回
    return result;
    */
}

//发送短信
//    Request URL: http://localhost/user/send-sms
//    Request Method: POST
@PostMapping(value = "/send-sms",produces = "text/html;charset=utf-8")
@ResponseBody
public String sendSMS(@RequestParam String phone, HttpSession session){
    //1. 调用工具发短信.
    String result = sendSMSUtil.sendSMS(session, phone);
    //2. 将result响应给ajax引擎.
    return result;
}

// 执行注册
//    Request URL: http://localhost/user/register
//    Request Method: POST
@PostMapping("/register")
public String register(@Valid User user, BindingResult bindingResult, HttpServletRequest request, String registerCode, HttpSession session, RedirectAttributes redirectAttributes) throws UnsupportedEncodingException {
    request.setCharacterEncoding("UTF-8");
    String username = request.getParameter("username");

    String contentType = request.getHeader("Content-Type");
    String method = request.getMethod();
    //1. 校验验证码.
    /*if(!StringUtils.isEmpty(registerCode)){
        // 验证码不为空,
        String code = (int) session.getAttribute(CODE) + "";
        if(!registerCode.equals(code)){
            // 验证码不正确
            redirectAttributes.addAttribute("registerInfo","验证码错误!");
            return REDIRECT + REGISTER_UI;
        }
    }*/
    //2. 校验参数是否合法.
    if(bindingResult.hasErrors() || StringUtils.isEmpty(registerCode)){
        // 参数不合法.
        String msg = bindingResult.getFieldError().getDefaultMessage();
        if(StringUtils.isEmpty(msg)){
            msg = "验证码为必填项,岂能不填!";
        }
        redirectAttributes.addAttribute("registerInfo",msg);
        return REDIRECT + REGISTER_UI;
    }
    //3. 调用service执行注册功能.
    Integer count = userService.register(user);
    //4. 根据service返回的结果跳转到指定页面.
    if(count == 1){
        // 注册成功.
        return REDIRECT + LOGIN_UI;
    }else{
        // 注册失败
        redirectAttributes.addAttribute("registerInfo","服务器爆炸了!!");
        return REDIRECT + REGISTER_UI;
    }
}


// 跳转到登录页面.
// GET  http://localhost/user/login-ui
@GetMapping("/login-ui")
public String loginUI(){
//        int i = 1 / 0;
    return "user/login";
}
// 执行登录
//    Request URL: http://localhost/user/login
//    Request Method: POST
@PostMapping("/login")
@ResponseBody
public ResultVO login(String username,String password){
    //1. 校验参数是否合法.
    if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
        // 参数不合法.
        return new ResultVO(1,"用户名和密码为必填项,岂能不填!",null);
    }
    //2. 调用service执行登录.
//        User user = userService.login(username,password);
    Subject subject = SecurityUtils.getSubject();
    try {
        subject.login(new UsernamePasswordToken(username,password));
        return new ResultVO(0,"成功",null);
    } catch (AuthenticationException e) {
        e.printStackTrace();
        return new ResultVO(2,"用户名或密码错误!",null);
    }

}

com.qf.Handler.MyExceptionHandler

package com.qf.handler;

import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
@Component
public class MyExceptionHandler {
@ExceptionHandler(Exception.class)
public String ex(Exception ex){
    ex.printStackTrace();
    return "error";
}

}

com.qf.inerceptor.AuthenticationInterceptor

package com.qf.interceptor;

import com.qf.constant.SsmConstant;
import com.qf.pojo.User;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
*  权限校验.
 */
public class AuthenticationInterceptor implements HandlerInterceptor {

// 前处理, 执行controller方法之前.
// 可以选择对请求进行拦截/放行
// return false -> 拦截.    return true -> 放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //1. 获得session.
    HttpSession session = request.getSession();
    //2. 通过session获取用户信息
    User user = (User) session.getAttribute(SsmConstant.USER);
    //3. 判断是否为null.
    if(user == null) {
        //3.1 为null -> 用户未登陆. -> 跳转到登陆页面.-> return false;
        response.sendRedirect(request.getContextPath() + "/user/login-ui");
        return false;
    }else {
        //3.2 不为null -> return true;
        return true;
    }
}

// 执行完controller,返回ModelAndView之后执行.
// 拦截器的post处理中,修改ModelAndView
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
                       Object handler, ModelAndView modelAndView) throws Exception {
}

// 拦截器后处理, 响应数据之前.
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}

}

com.qf.mapper.ItemMapper

package com.qf.mapper;

import com.qf.pojo.Item;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * item的dao层接口.
*/
public interface ItemMapper {

//1. 查询商品的总条数
Long findCountByName(@Param("name")String name);

//2. 分页查询商品的具体信息
List<Item> findItemByNameLikeAndLimit(@Param("name")String name,
                                      @Param("offset")Integer offset,
                                      @Param("size")Integer size);

//3. 添加商品
Integer save(Item item);

//4. 删除商品
Integer delById(@Param("id") Long id);

}

com.qf.mapper.UserMapper

package com.qf.mapper;

import com.qf.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.Set;

/**
 * 映射user用户表的mapper接口
* create by 郑大仙丶
 * 2019/7/15 10:55
 */
public interface UserMapper {

//1. 根据用户名查询数据条数
Integer findCountByUsername(@Param("username")String username);

//2. 添加用户信息
Integer save(User user);

//3. 根据用户名查询用户信息.
User findByUsername(@Param("username")String username);

//4. 查询今日过生日的用户
Set<User> findTodayPassBirthdayUser();

}

com.qf.pojo.Item

package com.qf.pojo;

import lombok.Data;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.format.annotation.DateTimeFormat;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Date;

/**
 *  商品表对应的实体类
*/
@Data
public class Item {

//id
public Long id;
// 商品名称
@NotBlank(message = "商品名称为必填项,岂能为空!")
private String name;
// 商品价格
@NotNull(message = "商品价格为必填项,岂能为空!")
private BigDecimal price;
// 商品的生产日期.
@DateTimeFormat(pattern = "yyyy-MM-dd")
@NotNull(message = "商品的生产日期为必填项,岂能为空!")
private Date productionDate;
// 商品的描述
@NotBlank(message = "商品描述为必填项,岂能为空!")
private String description;
// 商品的图片
private String pic;
// 商品的创建时间
private Date created;

}

com.qf.pojo.User

package com.qf.pojo;

import lombok.Data;
import org.hibernate.validator.constraints.NotBlank;

import java.util.Date;

/**
 * user表映射的实体类.
* create by 郑大仙丶
 * 2019/7/15 14:32
 */
@Data
public class User {

private Long id;

@NotBlank(message = "用户名为必填项,岂能不填!")
private String username;
@NotBlank(message = "密码为必填项,岂能不填!")
private String password;
@NotBlank(message = "手机号为必填项,岂能不填!")
private String phone;

// 盐
private String salt;

private Date birthday;

private String email;

private Date created;

}

com.qf.quartz.MyJobDetail

package com.qf.quartz;
public class MyJobDetail {

public void say(){
    System.out.println("嘿嘿嘿!!");
}

}

com.qf.quartz.SendMailTask

package com.qf.quartz;

import com.qf.pojo.User;
import com.qf.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Set;

public class SendMailTask {

private final String FROM = "zjw_2301211@126.com";

private final String FROM_PWD = "z123123";

@Autowired
private UserService userService;

@Autowired
private SendMailUtil sendMailUtil;

public void sendBirthdayMail() throws Exception {
    //1. 调用service获取今日过生日的用户
    Set<User> userList = userService.findTodayPassBirthdayUser();
    //2. 判断是否有内容
    if(userList != null && userList.size() > 0){
        // 有过生日的用户.
        for (User user : userList) {
            String subject = "生日快乐!";
            String content = "<h1 style='color:red;'>祝" + user.getUsername() + "生日快乐!!!!!</h1>";
            sendMailUtil.sendMail(FROM,user.getEmail(),FROM_PWD,subject,content);
        }
    }
}

}

com.qf.quartz.SendMailUtil

package com.qf.quartz;

import org.junit.Test;
import org.springframework.stereotype.Component;

import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Properties;

public class SendMailUtil {

// 创建邮件,
public MimeMessage createMail(Session session,String from,String to,String subject,String content) throws Exception {
    /*//1. 创建Properties对象.发送邮件时的配置信息.
    Properties props = new Properties();
    //2. 创建会话对象.    session.
    Session session = Session.getInstance(props);*/
    //3. 通过session创建邮件对象.
    MimeMessage message = new MimeMessage(session);
    //4. 设置发件人.
    message.setFrom(new InternetAddress(from));
    //5. 设置收件人(抄送人,密送人.)
    message.setRecipients(Message.RecipientType.TO,to);
    //6. 设置主题 subject.
    message.setSubject(subject,"UTF-8");
    //7. 设置邮件的内容 content.
    message.setContent(content,"text/html;charset=UTF-8");
    //8. 设置发送邮件的时间.
    message.setSentDate(new Date());
    //9. 保存邮件.
    message.saveChanges();
    return message;
}

/**
 * 发送邮件
 * @param from
 * @param to
 * @param fromPwd
 * @param subject
 * @param content
 * @throws Exception
 */
public void sendMail(String from,String to,String fromPwd,String subject,String content) throws Exception {
    //1. 创建Properties对象.
    Properties props = new Properties();

    //2. 设置发送邮件时的配置信息.
    //2.1 设置发送邮件使用的协议.  smtp - simple mail transfer protocol
    props.setProperty("mail.transport.protocol","smtp");
    //2.2 邮件邮件服务器的地址.    smtp.126.com
    props.setProperty("mail.smtp.host","smtp.126.com");
    //2.3 开启权限校验             true
    props.setProperty("mail.smtp.auth","true");

    //3. 获取session会话对象.
    Session session = Session.getInstance(props);

    //4. 设置打印日志.
    session.setDebug(true);

    //5. 创建邮件.
    MimeMessage message = this.createMail(session,from,to,subject,content);

    //6. 获取发送邮件的transport对象.
    Transport transport = session.getTransport();

    //7. 设置连接邮箱服务器的用户名和授权码|独立密码
    transport.connect(from,fromPwd);

    //8. 发送邮件.
    transport.sendMessage(message,message.getAllRecipients());

    //9. 释放资源.
    transport.close();
}

}

com.qf.realm.CustomRealm

package com.qf.realm;

import com.qf.pojo.User;
import com.qf.service.UserService;
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.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;

@Component
public class CustomRealm extends AuthorizingRealm {

@Autowired
private UserService userService;

{
    HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
    matcher.setHashAlgorithmName("MD5");
    matcher.setHashIterations(1024);
    this.setCredentialsMatcher(matcher);
}

public static void main(String[] args) {
    String pwd = new Md5Hash("123123","bb85248d-22e3-4017-a945-9187bc6963ab",1024).toString();
    System.out.println(pwd);
    // 123123:9c3b5c0672cd599ccf1019bddaa8089b
    // 123123:bb85248d-22e3-4017-a945-9187bc6963ab:1024: 149647a7f1066c592385f19e2a37fbb4
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//        1. 获取用户名.
    String username = (String) token.getPrincipal();

//        2. 根据用户名查询密码.
    User user = userService.findByUsername(username);
//        User user = this.findByUsername(username);
//        3. 如果密码为null -> 抛出UnknowAccountException
    if (user == null){
        return null;
    }
//        4.1 将用户名和查询到的密码封装到返回结果, Info中, 返回由更底层的代码做密码校验.
    SimpleAuthenticationInfo info = new 	SimpleAuthenticationInfo(user,user.getPassword(),"CustomRealm");
//        4.1 设置盐
    info.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt()));
//        5. 返回info.
    return info;
}

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    //1. 获取用户名称.
    String username = ((User) principals.getPrimaryPrincipal()).getUsername();
    //2. 通过用户名称查询全部的角色信息.
    Set<String> roles  = userService.findRolesByUsername(username);
	//        Set<String> roles  = this.findRolesByUsername(username);
    //3. 通过角色信息查询到全部的权限信息.
    Set<String> perms = userService.findPermissionsByRoles(roles);
	//        Set<String> perms = this.findPermsByRoles(roles);
    //4. 封装返回结果info,角色信息和权限信息设置进去.
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    info.setRoles(roles);
    info.setStringPermissions(perms);
    //5. 返回
    return info;
}

}

com.qf.service.ItemService

package com.qf.service;
import com.qf.pojo.Item;
import com.qf.util.PageInfo;

/**
 * item的Service层接口
 */
public interface ItemService {
// 分页查询商品信息
PageInfo<Item> findItemByNameLikeAndLimit(String name, Integer page, Integer size);
// 添加商品
Integer save(Item item)
// 根据id删除商品
Integer del(Long id);

}

com.qf.service.UserService

package com.qf.service;

import com.qf.pojo.User;

import java.util.Set;

public interface UserService {

// 根据用户名查询是否可用
Integer checkUsername(String username);

// 注册功能
Integer register(User user);

// 执行登录
User login(String username, String password);

// 根据用户名查询用户信息
User findByUsername(String username);

// 根据用户名查询用户角色
Set<String> findRolesByUsername(String username);

// 根据角色信息查询权限信息
Set<String> findPermissionsByRoles(Set<String> roles);

// 查询今天过生日的用户
Set<User> findTodayPassBirthdayUser();

}

com.qf.impl.ItemServiceImpl

package com.qf.service.impl;

import com.qf.mapper.ItemMapper;
import com.qf.pojo.Item;
import com.qf.service.ItemService;
import com.qf.util.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * item的service实现类
 */
@Service
public class ItemServiceImpl implements ItemService {

@Autowired
private ItemMapper itemMapper;

@Override
public PageInfo<Item> findItemByNameLikeAndLimit(String name, Integer page, Integer size) {
    //将PageInfo创建出来,并且封装list集合,再返回
    //1. 查询数据总条数.
    Long total = itemMapper.findCountByName(name);
    //2. 创建pageInfo对象.
    PageInfo<Item> pageInfo = new PageInfo<>(page,size,total);
    //3. 查询商品信息list.
    List<Item> list = itemMapper.findItemByNameLikeAndLimit(name, pageInfo.getOffset(), pageInfo.getSize());
    //4. 将list集合set到PageInfo中.
    pageInfo.setList(list);
    //5. 返回
    return pageInfo;
}

@Override
@Transactional
public Integer save(Item item) {
    return itemMapper.save(item);
}

@Override
@Transactional
public Integer del(Long id) {
    return itemMapper.delById(id);
}

}

com.qf.service.impl.UserServiceImpl

package com.qf.service.impl;

import com.qf.mapper.UserMapper;
import com.qf.pojo.User;
import com.qf.service.UserService;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Set;
import java.util.UUID;

@Service
public class UserServiceImpl implements UserService {

@Autowired
private UserMapper userMapper;

@Override
public Integer checkUsername(String username) {
    // 健壮性代码..
    if(!StringUtils.isEmpty(username)){
        username = username.trim();
    }
    Integer count = userMapper.findCountByUsername(username);
    return count;
}

@Override
public Integer register(User user) {
    //0. 生成盐
    String salt = UUID.randomUUID().toString();
    user.setSalt(salt);
    //1. 对密码加密.
    String newPwd = new Md5Hash(user.getPassword(),salt,1024).toString();
    user.setPassword(newPwd);
    //2. 调用mapper保存数据.
    Integer count = userMapper.save(user);
    //3. 返回信息
    return count;
}

@Override
public User login(String username, String password) {
    //1. 根据用户名查询用户信息.
    User user = userMapper.findByUsername(username);
    //2. 判断查询的结果是否为null.
    if(user != null) {
        //2.1 如果不为null -> 判断密码.
        String newPwd = new Md5Hash(password,null,1024).toString();
        //3. 如果密码正确,直接返回查询到user.
        if(user.getPassword().equals(newPwd)){
            // 登录成功,返回user对象
            return user;
        }
    }
    //4. 其他情况统一返回null.
    return null;
}

@Override
public User findByUsername(String username) {
    return userMapper.findByUsername(username);
}

@Override
public Set<String> findRolesByUsername(String username) {
    return null;
}

@Override
public Set<String> findPermissionsByRoles(Set<String> roles) {
    return null;
}

@Override
public Set<User> findTodayPassBirthdayUser() {
    return userMapper.findTodayPassBirthdayUser();
}

}

com.qf.test.CreateMail

package com.qf.test;

import org.junit.Test;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Date;
import java.util.Properties;

public class CreateMail {
// 创建邮件,
public MimeMessage createMail(Session session) throws Exception {
    /*//1. 创建Properties对象.发送邮件时的配置信息.
    Properties props = new Properties();
    //2. 创建会话对象.    session.
    Session session = Session.getInstance(props);*/
    //3. 通过session创建邮件对象.
    MimeMessage message = new MimeMessage(session);
    //4. 设置发件人.
    message.setFrom(new InternetAddress("zjw_2301211@126.com"));
    //5. 设置收件人(抄送人,密送人.)
    message.setRecipients(Message.RecipientType.TO,"402424668@qq.com");
    //6. 设置主题 subject.
    message.setSubject("测试邮件发送","UTF-8");
    //7. 设置邮件的内容 content.
    message.setContent("<h1>测试邮件发送</h1>","text/html;charset=UTF-8");
    //8. 设置发送邮件的时间.
    message.setSentDate(new Date());
    //9. 保存邮件.
    message.saveChanges();
    return message;
}

// 发送邮件.
@Test
public void sendMail() throws Exception {
    //1. 创建Properties对象.
    Properties props = new Properties();
    //2. 设置发送邮件时的配置信息.
    //2.1 设置发送邮件使用的协议.  smtp - simple mail transfer protocol
    props.setProperty("mail.transport.protocol","smtp");
    //2.2 邮件邮件服务器的地址.    smtp.126.com
    props.setProperty("mail.smtp.host","smtp.126.com");
    //2.3 开启权限校验             true
    props.setProperty("mail.smtp.auth","true");
    //3. 获取session会话对象.
    Session session = Session.getInstance(props);
    //4. 设置打印日志.
    session.setDebug(true);
    //5. 创建邮件.
    MimeMessage message = this.createMail(session);
    //6. 获取发送邮件的transport对象.
    Transport transport = session.getTransport();
    //7. 设置连接邮箱服务器的用户名和授权码|独立密码
    transport.connect("zjw_2301211@126.com","z123123");
    //8. 发送邮件
    transport.sendMessage(message,message.getAllRecipients());
    //9. 释放资源.
    transport.close();
}
// 发件人邮箱地址.
// 发件人授权码.
// 收件人邮箱地址.
// 邮件的主题.
// 邮件的内容

}

com.qf.util.PageInfo

package com.qf.util;
import lombok.Data;
import java.util.List;

@Data
public class PageInfo<T> {
// 商品信息和分页信息
//    当前页
private Integer page;       // 已知
//    每页显示条数
private Integer size;       // 已知
//    查询总条数.
private Long total;         // 已知
//    计算总页数.
private Integer pages;      // total % size == 0 ? total / size : total / size + 1;
//    计算起始索引.
private Integer offset;     // (page - 1) * size;
//    商品信息
private List<T> list;       // 查询得到.
//                      0
public PageInfo(Integer page, Integer size, Long total) {
    this.page = page <= 0 ? 1 : page;
    this.size = size <= 0 ? 5 : size;
    this.total = total < 0 ? 0 : total;
    // 计算出pages和offset;
    this.pages = (int) (this.total % this.size == 0 ? this.total / this.size : this.total / this.size + 1);
    this.offset = (this.page - 1) * this.size;
}

}

com.qf.util.SendSMSUtil

package com.qf.util;

import static com.qf.constant.SsmConstant.*;

import com.qf.constant.SsmConstant;
import com.yunpian.sdk.YunpianClient;
import com.yunpian.sdk.model.Result;
import com.yunpian.sdk.model.SmsSingleSend;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import java.util.Map;

@Component
public class SendSMSUtil {

@Value("${apikey}")
private String apikey;

public String sendSMS(HttpSession session,String phone){
    //初始化clnt,使用单例方式
    YunpianClient clnt = new YunpianClient(apikey).init();
    // 生成6位随机数
    int code = (int)((Math.random()*9+1)*100000);
    // 将正确的验证码设置到session域中
    session.setAttribute(CODE,code);
    System.out.println(code);
    //发送短信API
    Map<String, String> param = clnt.newParam(2);
    param.put(YunpianClient.MOBILE, phone);
    param.put(YunpianClient.TEXT, "【云片网】您的验证码是" + code);
    Result<SmsSingleSend> r = clnt.sms().single_send(param);
    //获取返回结果,返回码:r.getCode(),返回码描述:r.getMsg(),API结果:r.getData(),其他说明:r.getDetail(),调用异常:r.getThrowable()
    //账户:clnt.user().* 签名:clnt.sign().* 模版:clnt.tpl().* 短信:clnt.sms().* 语音:clnt.voice().* 流量:clnt.flow().* 隐私通话:clnt.call().*
    //释放clnt
    clnt.close();
    return r.getMsg();
}

}

com.qf.vo.ResultVO

package com.qf.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ResultVO {
private Integer code;
private String msg;
private Object data;
}

resources.mapper.ItemMapper

<?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.qf.mapper.ItemMapper">
<!--    //1. 查询商品的总条数-->
<!--    Long findCountByName(@Param("name")String name);-->
<select id="findCountByName" resultType="Long">
    select count(1) from item
    <where>
        <if test="name != null and name != ''">
            name like "%"#{name}"%"
        </if>
    </where>
</select>

<!--    //2. 分页查询商品的具体信息-->
<!--    List<Item> findItemByNameLikeAndLimit(@Param("name")String name,-->
<!--                                            @Param("offset")String offset,-->
<!--                                            @Param("size")String size);-->
<select id="findItemByNameLikeAndLimit" resultType="Item">
    select * from item
    <where>
        <if test="name != null and name != ''">
            name like "%"#{name}"%"
        </if>
    </where>
    order by created desc
    limit #{offset},#{size}
</select>

<!--    //3. 添加商品-->
<!--    Integer save(Item item);-->
<insert id="save" parameterType="Item">
    insert into
        item
    (name,price,production_date,description,pic)
        values
    (#{name},#{price},#{productionDate},#{description},#{pic})
</insert>

<!--    //4. 删除商品-->
<!--    Integer delById(@Param("id") Long id);-->
<delete id="delById" >
    delete from item where id = #{id}
</delete>

< /mapper>

resources.mapper.UserMapper

<?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.qf.mapper.UserMapper”>

<!--//1. 根据用户名查询数据条数-->
<!--Integer findCountByUsername(@Param("username")String username);-->
<select id="findCountByUsername" resultType="Integer">
    select count(1) from user where username = #{username}
</select>

<!--//2. 添加用户信息-->
<!--Integer save(User user);-->
<insert id="save" parameterType="User">
    insert into
      user
    (username,password,salt,phone)
      values
    (#{username},#{password},#{salt},#{phone})
</insert>

<!--    //3. 根据用户名查询用户信息.-->
<!--    User findByUsername(@Param("username")String username);-->
<select id="findByUsername" resultType="User">
    select * from user where username = #{username}
</select>

<!--    //4. 查询今日过生日的用户-->
<!--    Set<User> findTodayPassBirthdayUser();-->
<select id="findTodayPassBirthdayUser" resultType="User" >
    select * from user where DATE_FORMAT(now(),'%m%d') = DATE_FORMAT(birthday,'%m%d');
</select>

< /mapper>

SpringBoot中slf4j的使用jxc

pom.xml

< ?xml version=“1.0” encoding=“UTF-8”?>
< project xmlns=“http://maven.apache.org/POM/4.0.0” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd”>

<	modelVersion>4.0.0</modelVersion>
<	parent>
    <	groupId>org.springframework.boot</groupId>
    <	artifactId>spring-boot-starter-parent</artifactId>
    <	version>2.0.6.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.qf</groupId>
<artifactId>jxc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jxc</name>
<description>Demo project for Spring Boot</description>

<properties>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <!--redis-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!--swagger-->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.9.2</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.9.2</version>
    </dependency>
    <!--druid-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.1.10</version>
    </dependency>
    <!--mapper-->
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-spring-boot-starter</artifactId>
        <version>2.1.5</version>
    </dependency>
    <!--pagehelper-->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper-spring-boot-starter</artifactId>
        <version>1.2.10</version>
    </dependency>
    <!--shiro-->
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring-boot-web-starter</artifactId>
        <version>1.4.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.1.0</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

< /project>

logback-spring.xml

<?xml version="1.0" encoding="UTF-8" ?>

< configuration>

<appender name="consoleLog" class="ch.qos.logback.core.ConsoleAppender">
    <layout class="ch.qos.logback.classic.PatternLayout">
        <pattern>
            %d - %msg%n
        </pattern>
    </layout>
</appender>

<appender name="fileInfoLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>ERROR</level>
        <onMatch>DENY</onMatch>
        <onMismatch>ACCEPT</onMismatch>
    </filter>
    <encoder>
        <pattern>
            %msg%n
        </pattern>
    </encoder>
    <!--滚动策略-->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--路径-->
        <fileNamePattern>D:logs/info.%d.log</fileNamePattern>
    </rollingPolicy>
</appender>

<appender name="fileErrorLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>ERROR</level>
    </filter>
    <encoder>
        <pattern>
            %msg%n
        </pattern>
    </encoder>
    <!--滚动策略-->
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--路径-->
        <fileNamePattern>D:logs/error.%d.log</fileNamePattern>
    </rollingPolicy>
</appender>

<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>

<root level="info">
    <appender-ref ref="consoleLog" />
    <appender-ref ref="fileInfoLog" />
    <appender-ref ref="fileErrorLog" />
</root>

< /configuration>

SaleServiceImpl使用log

package com.qf.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qf.entity.Sale;
import com.qf.enums.JxcEnum;
import com.qf.exception.JxcException;
import com.qf.mapper.SaleMapper;
import com.qf.service.ProductService;
import com.qf.service.SaleService;
import com.qf.vo.PageVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;

@Service
@Slf4j
public class SaleServiceImpl implements SaleService {

@Autowired
private SaleMapper saleMapper;

@Autowired
ProductService productService;

@Override
public PageVO<Sale> findAllByPage(Integer page, Integer size, Integer flag) {
    PageHelper.startPage(page,size);
    List<Sale> sales = saleMapper.findSaleByFlag(flag);
    PageInfo<Sale> salePageInfo = new PageInfo<>(sales);
    PageVO<Sale> salePageVO = new PageVO<>(salePageInfo.getPageNum(),salePageInfo.getPageSize(),salePageInfo.getTotal(),salePageInfo.getPages(),salePageInfo.getList());
    return salePageVO;
}

@Override
@Transactional
public void save(Sale sale) {
    productService.reduceStock(sale.getProductId(),sale.getQuantity());
    BigDecimal price = sale.getPrice();
    Integer quantity = sale.getQuantity();
    BigDecimal multiply = price.multiply(new BigDecimal(quantity));
    sale.setTotalPrice(multiply);
    int i = saleMapper.insertSelective(sale);
    if (i != 1){
        log.error("[保存销售记录] 保存失败 sale = {}",sale);
        throw new JxcException(JxcEnum.SALE_SAVE_ERROR);
    }
}

}

Exception的使用,jxc-SpringBoot

com.enums.JxcEnum

package com.qf.enums;
import lombok.Getter;

@Getter
public enum  JxcEnum {
PARAMETER_ERROR(1,"参数不合法"),
USERNAME_ERROR(2,"用户名错误"),
PASSWORD_ERROR(3,"密码错误"),
UNKNOWN_ERROR(4,"未知错误"),
USER_NOT_LOGIN(5,"用户未登录"),
STOCK_NOT_ENOUGH(6,"库存不足"),
REDUCE_STOCK_ERROR(7,"削减库存失败"),
PRODUCT_NOT_EXIST(8,"商品不存在"),
SALE_SAVE_ERROR(9,"保存失败"),
;
private Integer code;
private String msg;
JxcEnum(Integer code, String msg) {
    this.code = code;
    this.msg = msg;
}

}

com.exception.JxcException

package com.qf.exception;

import com.qf.enums.JxcEnum;
import lombok.Getter;

@Getter
public class JxcException extends RuntimeException{
private Integer code;
public JxcException(Integer code,String message){
    super(message);
    this.code = code;
}
public JxcException(JxcEnum jxcEnum){
    super(jxcEnum.getMsg());
    this.code = jxcEnum.getCode();
}

}

com.controller.UserController使用自定义Exception

package com.qf.controller;

import com.qf.entity.User;
import com.qf.enums.JxcEnum;
import com.qf.service.UserService;
import com.qf.util.R;
import com.qf.vo.ResultVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
@Slf4j
@CrossOrigin(allowCredentials = "true")
@Api(tags = "用户模块接口")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/login")
@ApiOperation(value = "用户登录接口")
@ApiImplicitParams({@ApiImplicitParam(name = "username",value = "请输入用户名",defaultValue = "lisi"),
        @ApiImplicitParam(name = "password",value = "请输入密码",defaultValue = "aaa")})
public ResultVO login(String username, String password){
    if (StringUtils.isEmpty(username)||StringUtils.isEmpty(password)){
        log.info("[用户登录]参数不合法,username = {},password = {}",username,password);
        return R.error(JxcEnum.PARAMETER_ERROR);
    }
    Subject subject = SecurityUtils.getSubject();
    try {
        subject.login(new UsernamePasswordToken(username,password));
    } catch (UnknownAccountException e) {
        e.printStackTrace();
        return R.error(JxcEnum.USERNAME_ERROR);
    }catch (IncorrectCredentialsException e){
        e.printStackTrace();
        return R.error(JxcEnum.PARAMETER_ERROR);
    }catch (Exception e){
        e.printStackTrace();
        return R.error(JxcEnum.UNKNOWN_ERROR);
    }
    return R.ok();
}

@GetMapping("/info")
@ApiOperation(value = "获取登录用户真实姓名")
public ResultVO info(){
    Subject subject = SecurityUtils.getSubject();
    User user = (User)subject.getPrincipal();
    if (user == null){
        log.info("[获取真实姓名] 用户未登录!!!");
        return R.error(JxcEnum.USER_NOT_LOGIN);
    }
    return R.ok(user.getRealname());
}

//public static void main(String[] args) {
//    System.out.println(new Md5Hash("aaa",null,1024).toString());
//}

@PostMapping("/logout")
@ApiOperation("退出登录")
public ResultVO logout(){
    Subject subject = SecurityUtils.getSubject();
    try {
        subject.logout();
    } catch (Exception e) {
        e.printStackTrace();
        return R.error(JxcEnum.UNKNOWN_ERROR);
    }
    return R.ok();
}

}

数据存到Redis-jxc

com.dao.RedisCache

package com.qf.dao;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import static com.qf.dao.RedisSessionDAO.*;

@Component
public class RedisCache<K,V> implements Cache<K,V> {

@Autowired
private RedisTemplate redisTemplate;

private final String SHIRO_CACHE_KEY = "shiro-cache-key:";

@Override
public V get(K k) throws CacheException {
    System.out.println("从redis中查询权限信息");
    //1.查询
    V v = (V)redisTemplate.opsForValue().get(SHIRO_CACHE_KEY + k);
    //2.重新设置生存时间
    redisTemplate.expire(k,TIME_OUT, TimeUnit.MINUTES);
    //3.返回
    return v;
}

@Override
public V put(K k, V v) throws CacheException {
    System.out.println("将权限信息放到redis中!");
    //1.设置值-并设置生存时间
    redisTemplate.opsForValue().set(SHIRO_CACHE_KEY + k,v,TIME_OUT,TimeUnit.MINUTES);
    //2.返回v
    return v;
}

@Override
public V remove(K k) throws CacheException {
    return null;
}

@Override
public void clear() throws CacheException {

}

@Override
public int size() {
    return 0;
}

@Override
public Set<K> keys() {
    return null;
}

@Override
public Collection<V> values() {
    return null;
}

}

RedisSessionDAO

package com.qf.dao;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisSessionDAO extends AbstractSessionDAO {

@Autowired
private RedisTemplate redisTemplate;

private final String SHIRO_KEY="shiro-sessison-key:";

public static final Long TIME_OUT = 10L;

//建立一个会话连接,存储到redis中
@Override
protected Serializable doCreate(Session session) {
    System.out.println("用户创建了session");
    //1.获取一个sessionId
    Serializable sessionId = super.generateSessionId(session);
    //2.将sessionId和session绑定到一起
    super.assignSessionId(session,sessionId);
    //3.将sessionId作为key,session作为value存储到redis中,并同时设置生存时间
    String key = SHIRO_KEY +sessionId;
    redisTemplate.opsForValue().set(key,session,TIME_OUT,TimeUnit.MINUTES);
    //4.返回sessionId
    return sessionId;
}

//获取session信息,去Redis中获取
@Override
protected Session doReadSession(Serializable serializable) {
    System.out.println("用户读取了session");
    //1.封装key
    String key = SHIRO_KEY + serializable;
    //2.去redis中查询session
    Session session = (Session)redisTemplate.opsForValue().get(key);
    //3.重新设置生存时间
    redisTemplate.expire(key,TIME_OUT,TimeUnit.MINUTES);
    //4.返回session
    return session;
}

//修改用户信息
@Override
public void update(Session session) throws UnknownSessionException {
    System.out.println("用户修改了session");
    //1.根据session获取sessionId
    Serializable id = session.getId();
    String key = SHIRO_KEY + id;
    redisTemplate.opsForValue().set(key,session,TIME_OUT,TimeUnit.MINUTES);
}

//退出登录,清空session
@Override
public void delete(Session session) {
    System.out.println("用户清空了session");
    Serializable id = session.getId();
    String key = SHIRO_KEY + id;
    redisTemplate.delete(key);
}

//获取存活的用户
@Override
public Collection<Session> getActiveSessions() {
    System.out.println("全部session信息已经获取");
    //1.封装pattern
    String pattern = SHIRO_KEY + "*";
    //2.声明返回结果集
    Set<Session> sessionSet = new HashSet<>();
    //3.通过keys查询全部存活的key
    Set keys = redisTemplate.keys(pattern);
    //4.遍历全部的key
    for (Object key : keys) {
        //通过key获取session,并添加到返回结果
       Session session = (Session) redisTemplate.opsForValue().get(key);
       sessionSet.add(session);
    }
    //5.返回结果集
    return sessionSet;
}

}

RedisSessionManager

package com.qf.dao;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.WebSessionKey;

import javax.servlet.ServletRequest;
import java.io.Serializable;

public class RedisSessionManager extends DefaultWebSessionManager {

@Override
protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
    //1.获取sessionId
    Serializable sessionId = getSessionId(sessionKey);
    if (sessionId == null){
        return null;
    }
    //2.先去request域中查询.
    WebSessionKey webSessionKey = (WebSessionKey) sessionKey;
    ServletRequest request = webSessionKey.getServletRequest();
    Session session = (Session)request.getAttribute(sessionId.toString());
    //3.如果没有结果查询
    if (session == null){
        //去redis中查询retriveSessionFromDataSource
        session = super.retrieveSessionFromDataSource(sessionId);
        //将查询结果放到request域中
        request.setAttribute(sessionId.toString(),session);
    }
    //4.返回session
    return session;
}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值