SSM整合配置(spirng, springmvc,mybatis)基于dubbo和zookeeper

1、web-controller层配置:

webapp:web.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

	<!--1.spring的web监听器-->
	<!--1.1 修改监听器加载的路径-->
	<!--这里必须配置classpath*: 因为要读取dao,service工程的applicationContext文件-->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:spring/applicationContext-*.xml</param-value>
	</context-param>
	<!--1.2 监听器-->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!--2.字符编码过滤器-->
	<filter>
		<filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
		<url-pattern>/*
	

	
	
		dispatcherServlet
		org.springframework.web.servlet.DispatcherServlet
		
		
			contextConfigLocation
			classpath:spring/springmvc.xml
		
		
		1
	
		
	
		dispatcherServlet
		*.do
	

	
	
	
		shiroFilter
		org.springframework.web.filter.DelegatingFilterProxy
		
		
			targetFilterLifecycle
			true
		
	
	
		shiroFilter
		/*
	


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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       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
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
       http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!--1.扫描Controller所在包(不要去扫描service)-->
    <context:component-scan base-package="cn.itcast.web"/>

    <!--2.配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--2.1 页面前缀 注意:放在WEB-INF下用户不能直接访问页面,更加安全-->
        <property name="prefix" value="/WEB-INF/pages/"/>
        <!--2.2 页面后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--3.mvc注解驱动-->
    <mvc:annotation-driven conversion-service="conversionService"/>

    <!--4.配置类型转换器-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <!--配置自定义转换器-->
        <property name="converters">
            <set>
                <bean class="cn.itcast.web.converter.StringToDateConverter"/>
            </set>
        </property>
    </bean>

    <!--5.配置自定义异常处理类-->
    <bean class="cn.itcast.web.exceptions.CustomExceptionRosolver"/>

    <!--6.开启AOP注解的支持-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

    <!--7.Dubbo配置-->
    <!--7.1指定服务名称-->
    <dubbo:application name="export_web_manager"/>

    <!--7.2zookeeper注册配置-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <!--7.3包扫描@Reference-->
    <dubbo:annotation package="cn.itcast.web"/>

    <!--文件上传相关配置-->
    <!--8.加载七牛qiniu.properties-->
    <context:property-placeholder location="classpath*:qiniu.properties"/>

    <!--8.2开启springmvc文件上传组件-->
    <!--注意:必须给id,而且名称必须叫multipartResolver-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--限制文件大小5M-->
        <property name="maxUploadSize" value="5242880"/>
    </bean>

</beans>

applicationContext-dubbo.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:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

    <!--dubbo服务提供方-->
    <!--1.dubbo的服务名称-->
    <dubbo:application name="export_web_manager"/>

    <!--2.注册中心的地址配置-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <!--3.扫描dubbo注解-->
    <dubbo:annotation package="cn.itcast.web"/>

    <!--手动远程注入dubbo服务,代替@Reference-->
    <!--
       dubbo:reference: 手动创建远程调用服务
          interface: 远程服务的接口
          id: 把远程服务引用对象放入IOC容器
    -->
    <dubbo:reference id="contractService" interface="cn.itcast.service.cargo.ContractService" timeout="100000"/>


</beans>

applicationContext-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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd ">

    <!--1.配置ShiroFilter对象,shiroFiter和web.xml配置filter-name保持一致-->
    <!--ShiroFilterFactoryBean:处理用户的认证和授权的请求的对象-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--注入SecurityManager-->
        <property name="securityManager" ref="securityManager"/>
        <!--修改shiro默认登录页面-->
        <property name="loginUrl" value="/login.jsp"/>
        <!--授权失败提示页面-->
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>

        <!--添加shiro的过滤器-->
        <property name="filterChainDefinitions">
            <!--
             注意:
              1)拦截路径问题
                * : 拦截一层目录
                **: 拦截任意层目录
              2)默认登录页面问题
                  Shiro认证失败了,自动跳转到login.jsp页面,可以通过loginUrl参数修改默认登录页面
                  anon代表不认证也可以访问(匿名访问),通常对静态资源进行放行
                  authc代表必须通过认证才可以访问,通常对动态资源(controller,jsp页面)进行拦截
                  perms 过滤器,就是进行权限校验的过滤器
            -->
            <value>
                /css/**=anon
                /img/**=anon
                /make/**=anon
                /plugins/**=anon
                /login.do=anon
                /company/list.do=perms["企业管理"]
                /system/module/list.do=perms["模块管理"]
                /system/user/list.do=perms["用户管理"]
                /system/dept/list.do=perms["部门管理"]
                /system/role/list.do=perms["角色管理"]
                /system/log/list.do==perms["日志管理"]
                /**=authc
            
        
    

    
    
        
        
    

    
    
        
        
    

    
        
   

    
    

    
    
    
    
        
    



applicationContext-rabbitmq-producer.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:rabbit="http://www.springframework.org/schema/rabbit"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/rabbit
       http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">

    <!--1.创建连接工厂-->
    <rabbit:connection-factory
            id="connectionFactory"
            host="127.0.0.1"
            port="5672"
            virtual-host="/heima"
            username="heima"
            password="123"
    />

    <!--2.配置admin:管理连接与频道-->
    <rabbit:admin connection-factory="connectionFactory"/>

    <!--3.声明队列(创建队列)-->
    <rabbit:queue name="contractQueue"/>

    <!--4.创建交换机,同时把队列绑定到交换机上-->
      <!--name:交换机的名称-->
    <rabbit:topic-exchange name="contractTopicExchange">
        <!--把队列绑定到交换机上-->
        <rabbit:bindings>
              <!--pattern: 指定routing key-->
              <!--queue: 绑定的队列名称-->
            <rabbit:binding pattern="contract.#" queue="contractQueue"></rabbit:binding>
        </rabbit:bindings>
    </rabbit:topic-exchange>

    <!--5.创建RabbitTemplate对象:封装RabbitMQ的Api-->
        <!--message-converter: 消息内容转换器-->
    <rabbit:template id="rabbitTemplate"
                     connection-factory="connectionFactory"
                     exchange="contractTopicExchange"
                     message-converter="messageConverter"
    />

    <!--6.配置Json转换器(MQ传输过程中,用于Java与Json字符串之间转换)-->
    <bean id="messageConverter" class="org.springframework.amqp.support.converter.Jackson2JsonMessageConverter"/>


</beans>

applicationContext-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">

    <!--1.创建任务对象-->
    <bean id="contractTask" class="cn.itcast.web.task.ContractTask"/>

    <!--2.创建JobDetail对象-->
    <bean id="JobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!--2.1 指定任务对象-->
        <property name="targetObject" ref="contractTask"/>
        <!--2.2 指定任务方法-->
        <property name="targetMethod" value="execute"/>
    </bean>

    <!--3.创建Trigger触发去-->
    <bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="JobDetail"/>
        <!--3.1任务表达式-->
        <property name="cronExpression" value="0/5 * * * * ? *"/>
    </bean>

    <!--4.创建Scheduler任务调度对象-->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <array>
                <ref bean="trigger"/>
            </array>
        </property>
    </bean>


</beans>

工具类:

发送邮件:


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

/**
 *  使用JavaMail发送邮件的工具类
 */
public class MailUtils {

    /**
     * 实现邮件发送的方法
     */
    public static void sendMsg(String to,String subjet,String content) throws Exception {
        // (一)建立和邮件发送服务的连接
        // 1.设置邮件服务器的参数
        Properties properties = new Properties();
        properties.setProperty("mail.smtp.host","smtp.sina.com"); // 设置主机地址  smtp.qq.com    smtp.sina.com

        properties.setProperty("mail.smtp.auth","true"); // 认证

        // 2. 产生一个用于邮件发送的Session对象
        Session session = Session.getInstance(properties);

        // (二) 编写一封邮件内容
        // 3. 产生一个邮件的消息对象
        MimeMessage message = new MimeMessage(session);

        // 4. 设置消息的发送者
        Address fromAddr = new InternetAddress("[email protected]");
        message.setFrom(fromAddr);

        // 5. 设置消息的接收者
        Address toAddr = new InternetAddress(to);
        // to 直接发送 cc 抄送  bcc密送
        message.setRecipient(MimeMessage.RecipientType.TO,toAddr);

        // 6. 设置主题
        message.setSubject(subjet);
        // 7. 设置正文
        message.setText(content);

        // (三)发送邮件
        // 8. 准备发送,得到火箭
        Transport transport = session.getTransport("smtp");
        // 9. 设置火箭的发射目标
        transport.connect("smtp.sina.com","[email protected]","loveyou");
        // 10. 发送
        transport.sendMessage(message,message.getAllRecipients());

        // 11. 关闭
        transport.close();

    }
}

文件下载:


import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class DownloadUtil {
	
	/**
	 * @param filePath 要下载的文件路径
	 * @param returnName 返回的文件名
	 * @param response HttpServletResponse
	 * @param delFlag 是否删除文件
	 */
	protected void download(String filePath,String returnName,HttpServletResponse response,boolean delFlag){
		this.prototypeDownload(new File(filePath), returnName, response, delFlag);
	}


	/**
	 * @param file 要下载的文件
	 * @param returnName 返回的文件名
	 * @param response HttpServletResponse
	 * @param delFlag 是否删除文件
	 */
	protected void download(File file,String returnName,HttpServletResponse response,boolean delFlag){
		this.prototypeDownload(file, returnName, response, delFlag);
	}
	
	/**
	 * @param file 要下载的文件
	 * @param returnName 返回的文件名
	 * @param response HttpServletResponse
	 * @param delFlag 是否删除文件
	 */
	public void prototypeDownload(File file,String returnName,HttpServletResponse response,boolean delFlag){
		// 下载文件
		FileInputStream inputStream = null;
		ServletOutputStream outputStream = null;
		try {
			if(!file.exists()) return;
			response.reset();
			//设置响应类型	PDF文件为"application/pdf",WORD文件为:"application/msword", EXCEL文件为:"application/vnd.ms-excel"。  
			response.setContentType("application/octet-stream;charset=utf-8");

			//设置响应的文件名称,并转换成中文编码
			//returnName = URLEncoder.encode(returnName,"UTF-8");
			returnName = response.encodeURL(new String(returnName.getBytes(),"iso8859-1"));	//保存的文件名,必须和页面编码一致,否则乱码
			
			//attachment作为附件下载;inline客户端机器有安装匹配程序,则直接打开;注意改变配置,清除缓存,否则可能不能看到效果
			response.addHeader("Content-Disposition",   "attachment;filename="+returnName);  
			
			//将文件读入响应流
			inputStream = new FileInputStream(file);
			outputStream = response.getOutputStream();
			int length = 1024;
			int readLength=0;
			byte buf[] = new byte[1024];
			readLength = inputStream.read(buf, 0, length);
			while (readLength != -1) {
				outputStream.write(buf, 0, readLength);
				readLength = inputStream.read(buf, 0, length);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				outputStream.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			//删除原文件
			
			if(delFlag) {				
				file.delete();
			}
		}
	}

	/**
	 * @param byteArrayOutputStream 将文件内容写入ByteArrayOutputStream
	 * @param response HttpServletResponse	写入response
	 * @param returnName 返回的文件名
	 */
	public void download(ByteArrayOutputStream byteArrayOutputStream, HttpServletResponse response, String returnName) throws IOException{
		response.setContentType("application/octet-stream;charset=utf-8");
		returnName = response.encodeURL(new String(returnName.getBytes(),"iso8859-1"));			//保存的文件名,必须和页面编码一致,否则乱码
		response.addHeader("Content-Disposition",   "attachment;filename=" + returnName);  
		response.setContentLength(byteArrayOutputStream.size());
		
		ServletOutputStream outputstream = response.getOutputStream();	//取得输出流
		byteArrayOutputStream.writeTo(outputstream);					//写到输出流
		byteArrayOutputStream.close();									//关闭
		outputstream.flush();											//刷数据
	}
}

对象属性转换:


import org.springframework.cglib.beans.BeanMap;

import java.util.HashMap;
import java.util.Map;

public class BeanMapUtils {

    /**
     * 将对象属性转化为map结合
     */
    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = new HashMap<>();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key+"", beanMap.get(key));
            }
        }
        return map;
    }

    /**
     * 将map集合中的数据转化为指定对象的同名属性中
     */
    public static <T> T mapToBean(Map<String, Object> map,Class<T> clazz) throws Exception {
        T bean = clazz.newInstance();
        BeanMap beanMap = BeanMap.create(bean);
        beanMap.putAll(map);
        return bean;
    }
}

日志通知:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;

/**
 * 日志切面类
 *      切面 = 通知+切入点
 */
@Aspect // 标记为切面类
@Component  // 把切面对象放入IOC容器中
public class LogAspect {
    // 注入数据
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private SysLogService sysLogService;
    @Autowired
    private HttpSession session;

    /**
     * 环绕通知方法:记录日志的方法
     *      ProceedingJoinPoint:控制目标对象的方法执行 或 获取目标对象的信息
     */
    @Around(value = "execution(* cn.itcast.web.controller.*.*.*(..))")
    public Object log(ProceedingJoinPoint jp){
        // result:目标对象的方法返回值
        Object result = null;

        // 1.获取当前登陆用户
        User loginUser = (User) session.getAttribute("loginUser");

        // 获取当前目标执行的方法
        // 2.getSignature:获取目标方法信息
        String methodName = jp.getSignature().getName();

        // 3.getTarget():获取目标对象
        String fullClassName = jp.getTarget().getClass().getName();
        try{
            // 创建对象
            SysLog sysLog = new SysLog();
            // 4 封装日志信息
            // 4.1 封装操作用户的信息
            if (loginUser != null){
                sysLog.setUserName(loginUser.getUserName());
                sysLog.setCompanyId(loginUser.getManagerId());
                sysLog.setCompanyName(loginUser.getCompanyName());
            }
            // 4.2 获取当前用的IP地址
            String ip = request.getLocalAddr();
            sysLog.setIp(ip);

            // 4.3 设置操作时间
            sysLog.setTime(new Date());

            // 4.4 设置方法名称
            sysLog.setMethod(methodName);

            // 4.5 设置操作的那个类
            sysLog.setAction(fullClassName);

            // 编写前置通知代码
            // 5.保存日志信息
            sysLogService.save(sysLog);

            // 编写后置通知代码
            // 6.执行目标对象的方法
            result = jp.proceed();

        }catch (Throwable throwable){
            // 异常通知代码
            throwable.printStackTrace();
        }finally {
            // 编写最终通知代码
        }
        return result;
    }

}

task消息队列,定时发送邮件:

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 每天早上10点,对交期还有2天的购销合同,发送提醒邮件
 */
public class ContractTask {
    // 通过本地方式 来注入 远程服务
    @Autowired
    @Qualifier("contractService") // Qualifier:指定bean的id进行注入
    private ContractService contractService;

    //注入RabbitTemplate对象
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void execute(){

//        System.out.println("触发了任务...");

        // 1.调用业务,查询还有2天到期的购销合同
        List<ContractTaskVo> list = contractService.findByPeriod(2);

        // 2.遍历,给每个合同创建人发送提醒邮件
        if (list != null && list.size() > 0){
            for (ContractTaskVo contractTaskVo :list){
              /*  // 交货期限
                Date deliveryPeriod = contractTaskVo.getDeliveryPeriod();
                String delvertyDate = new SimpleDateFormat("yyyy-MM-dd").format(deliveryPeriod);

                // 收件人
                String receiver = contractTaskVo.getEmail();
                // 标题
                String title = "交货期限到期提醒邮件";
                // 内容
                String content = "尊敬的"+contractTaskVo.getUserName()+":你有一个合同(合同号):"
                        +contractTaskVo.getContractNo()+"在"+delvertyDate+"到期,请及时处理,如果已经处理请忽略";

                // 发送邮件
                try {
                    MailUtils.sendMsg("[email protected]",title,content);
                    System.out.println("发送成功");
                } catch (Exception e) {
                    e.printStackTrace();
                }*/

                //异步发送消息到RabbitMQ
              rabbitTemplate.convertAndSend("contract.delivery",contractTaskVo);

            }
        }

    }
}

用户认证和授权:

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

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

/**
 * 用户的认证和授权的Realm
 */
public class AuthRealm extends AuthorizingRealm {
    // 注入serssion
    @Autowired
    private UserService userService;

    /**
     * 认证方法,该方法编写认证逻辑
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //System.out.println("认证方法");

        // 1.判断用户名是否存在
        // 1.1 获取当前用户输入的登录数据
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        // 1.2获取登录时的用户名
        String email = token.getUsername();

        //1.3查询数据库判断邮箱是否存在
        User loginUser = userService.findByEmail(email);

        // 1.4 判断用户是否存在
        if (loginUser == null){
            // 用户不存在
            return null; // 只需要返回null,Shiro自动抛出UnknownAccountException异常
        }
        //2.返回数据库的密码,让Shiro判断密码是否正确
        /**
         * 参数一:用户登录成功后,需要获取的登录数据(使用Subject.getPrincipal获取的)
         * 参数二:(最重要)数据库的密码
         * 参数三:只有在多个Realm(多张用户表)的情况下才有用的(如果只有一个Realm可以随便写)
         */
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(loginUser,loginUser.getPassword(),loginUser.getUserName());
        return info;
    }

    /**
     * 授权方法,该方法编写授权逻辑
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//        System.out.println("授权方法");

        // 1.创建SimpleAuthorizationInfo授权对象
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        // 2.根据当前登录用户查询分配的权限(模块)
        // 2.1 获取登录用户的信息
        Subject subject = SecurityUtils.getSubject();
        User loginUser = (User) subject.getPrincipal();

        // 2.2 查询用户分配的权限
        List<Module> moduleList = userService.findModulesByUserId(loginUser.getId());

        // 3. 把模块的权限标记(cpermission字段值)存入授权对象
        Set<String> permissions = new HashSet<>();

        // 3.1 遍历所有模块数据
        if(moduleList!=null && moduleList.size()>0){
            for(Module module:moduleList){
                //3.2 存入模块的权限标记(cpermission字段值)
                if(module.getCpermission()!=null){
                    permissions.add(module.getCpermission());
                }
            }
        }
        // 3.3 把所有权限标记的Set集合存入info对象中
        info.addStringPermissions(permissions);

        // 4.返回授权对象
        return info;
    }
}

密码加盐加密:

package cn.itcast.web.shiro;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.crypto.hash.Md5Hash;

/**
 * 自定义凭证匹配器(加盐加密)
 */
public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {
    /**
     * 编写凭证匹配逻辑
     * @param token  用户输入的登录信息
     * @param info Realm返回的封装数据库的信息
     * @return true: 密码一致
     *         false  密码不一致
     */
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        // 1.从token获取用户输入用户名(盐)和(密码(源密码)
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        String email = userToken.getUsername(); // 用户名(盐)
        char[] password = userToken.getPassword(); //  密码

        // 2.使用Md5Hash对源密码进行加盐加密,得到新密码
        Md5Hash md5Hash = new Md5Hash(password,email);
        String encodePwd = md5Hash.toString();

        // 3.从Info取出数据库的密码(加密的)
        //getCredentials: 取出AuthRealm的SimpleAuthenticationInfo对象的第二个参数的内容
        Object dbPwd = info.getCredentials();

        // 4.使用新密码和数据库密码比较,如果相等,返回true,否则flase;
        return encodePwd.equals(dbPwd);
    }
}

日期转换类型

import org.springframework.core.convert.converter.Converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 日期类型转换器
 *  泛型一:源类型
 *  泛型二:目标类型
 */
public class StringToDateConverter implements Converter<String,Date>{
    @Override
    public Date convert(String s) {
        Date date = null;

        try {
            date =  new SimpleDateFormat("yyyy-MM-dd").parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}

异常处理:

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

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

/**
 * 定制的全局异常处理类
 */
public class CustomExceptionRosolver implements HandlerExceptionResolver {

    /**
     *该方法在控制器的任何方法出现异常就会执行(注意:在控制器不能自行处理异常,不要自己try catch)
     * 方法参数:
     *       request:请求对象
     *       response:响应对象
     *       handler:抛出异常的处理器方法(HandlerMethod)
     *       ex:异常对象
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ModelAndView mv = new ModelAndView();

        //1.存入异常信息
        mv.addObject("errorMsg","对不起,我错误了:"+ex.getMessage());

        //2.跳转到错误提示页面
        mv.setViewName("error");

        return mv;
    }
}

2、service远程调用:

sevice层配置dubbo注册地址applicationContext-dubbo.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:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

        <!--dubbo服务提供方-->
    <!--1.dubbo的服务名称-->
        <dubbo:application name="export_cargo_service"/>

    <!--2.注册中心的地址配置-->
    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>

    <!--3.dubbo协议-->
    <dubbo:protocol name="dubbo" port="20882"/>

    <!--4.扫描dubbo注解-->
    <dubbo:annotation package="cn.1111.service"/>

</beans>

tomcat启动配置web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

	<!--加载dubbo配置-->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:spring/applicationContext-*.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>


</web-app>

基于main方法的启动配置:


import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
 * 基于main方法启动提供者
 */
public class ContractProvider {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext context =  new ClassPathXmlApplicationContext("classpath*:spring/applicationContext-*.xml");

        context.start();

        System.in.read();
    }
}

3、rabbitMQ消息队列

applicationContext-rabbitmq-consumer.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:rabbit="http://www.springframework.org/schema/rabbit"
       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/rabbit
       http://www.springframework.org/schema/rabbit/spring-rabbit.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">


    <!--1.创建连接工厂-->
    <rabbit:connection-factory
            id="connectionFactory"
            host="127.0.0.1"
            port="5672"
            virtual-host="/heima"
            username="heima"
            password="123"
    />

    <!--2.配置admin:管理连接与频道-->
    <rabbit:admin connection-factory="connectionFactory"/>


    <!-- 3.扫描监听程序,创建对象-->
    <context:component-scan base-package="cn.itcast.listener"/>

    <!-- 4.配置消息监听容器-->
    <rabbit:listener-container connection-factory="connectionFactory">
        <!--配置监听程序-->
        <!--
          ref:引用监听程序
          queue-names: 需要监听的队列名称列表
        -->
        <rabbit:listener ref="contractEmailListener" queue-names="contractQueue"/>
    </rabbit:listener-container>

</beans>

登录发送邮件工具类:

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

/**
 * 电子邮件工具类
 *
 * @author Administrator
 */
public class MailUtil {
    //实现邮件发送的方法
    public static void sendMsg(String to, String subject, String content) throws Exception {
        Properties props = new Properties();
        props.setProperty("mail.smtp.host", "smtp.sina.com");  //设置主机地址   smtp.qq.com    smtp.sina.com

        props.setProperty("mail.smtp.auth", "true");//认证

        //2.产生一个用于邮件发送的Session对象
        Session session = Session.getInstance(props);

        //3.产生一个邮件的消息对象
        MimeMessage message = new MimeMessage(session);

        //4.设置消息的发送者
        Address fromAddr = new InternetAddress("[email protected]");
        message.setFrom(fromAddr);

        //5.设置消息的接收者
        Address toAddr = new InternetAddress(to);
        //TO 直接发送  CC抄送    BCC密送
        message.setRecipient(MimeMessage.RecipientType.TO, toAddr);

        //6.设置主题
        message.setSubject(subject);
        //7.设置正文
        message.setText(content);

        //8.准备发送,得到火箭
        Transport transport = session.getTransport("smtp");
        //9.设置火箭的发射目标
        transport.connect("smtp.sina.com", "[email protected]", "loveyou");
        //10.发送
        transport.sendMessage(message, message.getAllRecipients());

        //11.关闭
        transport.close();
    }
}

监听到期内容:


import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 内容到期消息监听器
 */
@Component
public class ContractEmailListener implements MessageListener {

    private ObjectMapper mapper = new ObjectMapper();

    @Override
    public void onMessage(Message message) {
        //1.获取消息内容
        byte[] body = message.getBody();

        //2.转换为JavaBean对象
        try {
            ContractTaskVo contractTaskVo = mapper.readValue(body, ContractTaskVo.class);

            //3.发送邮件
            Date deliveryPeriod = contractTaskVo.getDeliveryPeriod();
            String delvertyDate = new SimpleDateFormat("yyyy-MM-dd").format(deliveryPeriod);

            //收件人
            String receiver = contractTaskVo.getEmail();
            //标题
            String title = "交货期限到期提醒邮件";
            //内容
            String content = "尊敬的" + contractTaskVo.getUserName() + ":你有一个合同(合同号:" + contractTaskVo.getContractNo() + "在" + delvertyDate + "到期,请请及时处理。如果已经处理请忽略。)";

            //发送邮件
            try {
                MailUtil.sendMsg("[email protected]", title, content);
                System.out.println("发送成功");
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4、门户入口:

web.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <!--1.启动springmvc,springmvc.xml配置dubbo-->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:spring/springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    <!--2.springmvc字符集编码过滤器-->
    <filter>
        <filter-name>characterEncodingFilter</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>characterEncodingFilter</filter-name>
        <url-pattern>/*
    


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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       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
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://code.alibabatech.com/schema/dubbo
       http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

        <!--1.springmvc配置,扫描Contexter-->
        <context:component-scan base-package="cn.itcast.web"/>

        <!--2.mvc注解的驱动-->
        <mvc:annotation-driven/>

        <!--3.dubbo服务消费配置-->
        <!--3.1 dubbo服务名称-->
        <dubbo:application name="export_web_portal"/>
        <!--3.2 zookeeper注册地址-->
        <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
        <!--3.3 扫描@Reference注解所在包-->
        <dubbo:annotation package="cn.111.web"/>

</beans>

5、父项目jar配置信息:

<?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>cn.itcast</groupId>  
  <artifactId>export_parent</artifactId>  
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>

<!--聚合项目-->
  <modules>
    <module>export_domain</module>
    <module>export_dao</module>
    <module>export_system_service</module>
    <module>export_web_manager</module>
      <module>export_company_interface</module>
      <module>export_company_service</module>
      <module>export_web_portal</module>
    <module>export_cargo_service</module>
    <module>export_cargo_interface</module>
      <module>export_stat_interface</module>
    <module>export_stat_service</module>
      <module>export_mq_consumer</module>
  </modules>


  <!-- 集中定义依赖版本号 -->
  <properties>
    <junit.version>4.12</junit.version>
    <spring.version>5.0.2.RELEASE</spring.version>
    <pagehelper.version>5.1.8</pagehelper.version>
    <servlet-api.version>2.5</servlet-api.version>
    <dubbo.version>2.8.4</dubbo.version>
    <zookeeper.version>3.4.7</zookeeper.version>
    <zkclient.version>0.1</zkclient.version>
    <mybatis.version>3.4.5</mybatis.version>
    <mybatis.spring.version>1.3.1</mybatis.spring.version>
    <mybatis.paginator.version>1.2.15</mybatis.paginator.version>
    <mysql.version>5.1.32</mysql.version>
    <druid.version>1.0.9</druid.version>
    <commons-fileupload.version>1.3.1</commons-fileupload.version>
    <jackson.version>2.9.5</jackson.version>
  </properties>

  <!--
          dependencies vs dependencyManagement的区别?
             1)在父工程使用dependencies,在子工程不需要导入依赖啦
             2)在父工程使用dependencyManagement,在在工程还是需要导入依赖,只是不写版本号而已啦
       -->
  <dependencies>
    <!-- Spring 依赖包-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!-- Dubbo依赖包 -->
    <dependency>
      <groupId>javassist</groupId>
      <artifactId>javassist</artifactId>
      <version>3.11.0.GA</version>
    </dependency>
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.10</version>
    </dependency>

    <!--web基础包 -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>2.5</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>

    <!-- Mybatis 依赖包-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>${mybatis.version}</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>${mybatis.spring.version}</version>
    </dependency>

    <!-- mybatis分页插件 -->
    <dependency>
      <groupId>com.github.miemiedev</groupId>
      <artifactId>mybatis-paginator</artifactId>
      <version>${mybatis.paginator.version}</version>
    </dependency>
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>${pagehelper.version}</version>
    </dependency>

    <!-- MySql -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
    </dependency>
    <!-- 连接池 -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>${druid.version}</version>
    </dependency>

    <!-- 文件上传组件 -->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>${commons-fileupload.version}</version>
    </dependency>

    <!-- spring整合rabbitmq -->
    <dependency>
      <groupId>org.springframework.amqp</groupId>
      <artifactId>spring-rabbit</artifactId>
      <version>2.0.1.RELEASE</version>
    </dependency>

    <!-- xml解析器通用包:CXF WebService框架 -->
    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpcore</artifactId>
      <version>4.4.4</version>
    </dependency>
    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <version>4.5.3</version>
    </dependency>
    <dependency>
      <groupId>dom4j</groupId>
      <artifactId>dom4j</artifactId>
      <version>1.6.1</version>
    </dependency>
    <dependency>
      <groupId>xml-apis</groupId>
      <artifactId>xml-apis</artifactId>
      <version>1.4.01</version>
    </dependency>

    <!--shiro-->
    <!--shiro和spring整合-->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-spring</artifactId>
      <version>1.3.2</version>
    </dependency>
    <!--shiro核心包-->
    <dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-core</artifactId>
      <version>1.3.2</version>
    </dependency>

    <!--测试-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <!-- jackson支持包 -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>${jackson.version}</version>
    </dependency>
      <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson.version}</version>
      </dependency>

    <!--日志包-->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.25</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>

    <!--JavaMail支持包-->
    <dependency>
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
      <version>1.4</version>
    </dependency>
    <!--定时任务 -->
    <dependency>
      <groupId>org.quartz-scheduler</groupId>
      <artifactId>quartz</artifactId>
      <version>2.2.3</version>
    </dependency>

  </dependencies>


</project>

你可能感兴趣的:(SSM整合)