尚好房是一个二手房管理服务平台,开放优质资源和线上能力,聚合线上线下二手房产资源,打造一个全方位二手房服务生态市场,为消费者提供优质房产服务资源。
基础框架:ssm |
---|
分布式框架:ssm + Dubbo + zk |
spring session redis实现session共享 |
数据缓存:redis |
图片服务器:七牛云 |
后台管理权限控制:spring-security |
前端用户登录判断:拦截器 |
原型设计:墨刀 |
后台管理模板:Thymeleaf |
前端技术:Vue+Axios |
最终分布式架构模块
shf-parent:根目录,管理子模块:
common-util:公共类模块
model:实体类模块
service:dubbo服务父节点
service-acl:权限服务模块
service-house:房源服务模块
service-user:用户服务模块
service-api:dubbo服务api接口
web:前端(dubbo服务消费者)
web-admin:后台管理系统
web-front:网站前端
模块调用关系,如图:
尚好房后台管理系统:http://139.198.152.148:8001/
尚好房前端:http://139.198.152.148:8002/
根据演示了解项目业务
数据库从资源文件中获取,导入数据库,数据库表如下:
如:实体类、工具类直接复制到项目模块使用,后续不做说明,其他资源需要时引入。
目前我们先搭建“尚好房”后台管理系统,先搭建为单体架构:SSM框架,后续我们通过SSM架构过渡到Dubbo通信的分布式架构。
SSM单体架构模块:
shf-parent:根目录,管理子模块:
common-util:公共类模块
model:实体类模块
web-admin:后台管理系统
搭建SSM架构我们分三步进行:
搭建项目结构、配置依赖关系
配置SSM环境
测试SSM环境
创建Maven Project,命名为shf-parent,版本号为1.0
在pom.xml文件中指定打包方式为pom
删除src目录
父工程管理依赖
<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.0modelVersion>
<groupId>com.atguigugroupId>
<artifactId>shf-parentartifactId>
<packaging>pompackaging>
<version>1.0version>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
<spring.version>5.0.5.RELEASEspring.version>
<thymeleaf.version>3.0.11.RELEASEthymeleaf.version>
<pagehelper.version>5.2.0pagehelper.version>
<servlet-api.version>2.5servlet-api.version>
<fastjson.version>1.2.29fastjson.version>
<mybatis.version>3.4.5mybatis.version>
<mybatis.spring.version>1.3.1mybatis.spring.version>
<mysql.version>5.1.46mysql.version>
<druid.version>1.1.12druid.version>
<commons-fileupload.version>1.3.1commons-fileupload.version>
<slf4j-version>1.7.30slf4j-version>
<logback-version>1.2.3logback-version>
<lombok.version>1.18.8lombok.version>
<dubbo.version>2.6.0dubbo.version>
<zookeeper.version>3.4.7zookeeper.version>
<junit.version>4.12junit.version>
<zkclient.version>0.1zkclient.version>
<qiniu.version>7.2.0qiniu.version>
<spring.security.version>5.2.7.RELEASEspring.security.version>
<thymeleaf-springsecurity5.version>3.0.4.RELEASEthymeleaf-springsecurity5.version>
<redis-session.version>1.3.5.RELEASEredis-session.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.sessiongroupId>
<artifactId>spring-session-data-redisartifactId>
<version>${redis-session.version}version>
dependency>
<dependency>
<groupId>org.thymeleaf.extrasgroupId>
<artifactId>thymeleaf-extras-springsecurity5artifactId>
<version>${thymeleaf-springsecurity5.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>${junit.version}version>
dependency>
<dependency>
<groupId>org.thymeleafgroupId>
<artifactId>thymeleaf-spring5artifactId>
<version>${thymeleaf.version}version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>${pagehelper.version}version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>${mybatis.version}version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>${mybatis.spring.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>${druid.version}version>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>${commons-fileupload.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>${fastjson.version}version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>${slf4j-version}version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>${logback-version}version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>${lombok.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>dubboartifactId>
<version>${dubbo.version}version>
dependency>
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
<version>${zookeeper.version}version>
dependency>
<dependency>
<groupId>com.github.sgroschupfgroupId>
<artifactId>zkclientartifactId>
<version>${zkclient.version}version>
dependency>
<dependency>
<groupId>javassistgroupId>
<artifactId>javassistartifactId>
<version>3.12.1.GAversion>
dependency>
<dependency>
<groupId>commons-codecgroupId>
<artifactId>commons-codecartifactId>
<version>1.10version>
dependency>
<dependency>
<groupId>com.qiniugroupId>
<artifactId>qiniu-java-sdkartifactId>
<version>${qiniu.version}version>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-webartifactId>
<version>${spring.security.version}version>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-configartifactId>
<version>${spring.security.version}version>
dependency>
dependencies>
dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>${servlet-api.version}version>
<scope>providedscope>
dependency>
dependencies>
project>
在父工程shf-parent
下新建module作为子工程命名为common-util
<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">
<parent>
<artifactId>shf-parentartifactId>
<groupId>com.atguigugroupId>
<version>1.0version>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>common-utilartifactId>
<packaging>jarpackaging>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
project>
common-util
项目引入依赖
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
dependency>
<dependency>
<groupId>org.thymeleafgroupId>
<artifactId>thymeleaf-spring5artifactId>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>dubboartifactId>
dependency>
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
dependency>
<dependency>
<groupId>com.github.sgroschupfgroupId>
<artifactId>zkclientartifactId>
dependency>
<dependency>
<groupId>javassistgroupId>
<artifactId>javassistartifactId>
dependency>
<dependency>
<groupId>commons-codecgroupId>
<artifactId>commons-codecartifactId>
dependency>
<dependency>
<groupId>com.qiniugroupId>
<artifactId>qiniu-java-sdkartifactId>
dependency>
dependencies>
拷贝工具类到common-util
项目中
在父工程shf-parent
下新建module作为子工程命名为model
<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">
<parent>
<artifactId>shf-parentartifactId>
<groupId>com.atguigugroupId>
<version>1.0version>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>modelartifactId>
<packaging>jarpackaging>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
project>
引入lombok依赖
<dependencies>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<scope>providedscope>
dependency>
dependencies>
拷贝实体类到model
工程中
在父工程shf-parent
下新建module作为子工程命名为web-admin
使用插件转成web项目
引入依赖
<dependencies>
<dependency>
<groupId>com.atguigugroupId>
<artifactId>common-utilartifactId>
<version>1.0version>
dependency>
<dependency>
<groupId>com.atguigugroupId>
<artifactId>modelartifactId>
<version>1.0version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.jettygroupId>
<artifactId>jetty-maven-pluginartifactId>
<version>9.4.15.v20190215version>
<configuration>
<scanIntervalSeconds>2scanIntervalSeconds>
<webAppConfig>
<contextPath>/contextPath>
webAppConfig>
<httpConnector>
<port>8000port>
httpConnector>
configuration>
plugin>
plugins>
build>
说明:web容器我们使用jetty,与tomcat一样,jetty更轻量级。
操作模块:web-admin
在resources目录添加:
logback.xml
<configuration debug="false">
<property name="LOG_HOME" value="logs" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
encoder>
appender>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
root>
configuration>
ssm分为三层:
controller、service与dao层
我们为每一层分配添加一个配置文件,方便配置文件管理:
spring-mvc.xml
spring-service.xml
spring-persist.xml
在resources目录下创建spring目录,在目录中添加:spring-persist.xml:
<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
https://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="username" value="${datasource.username}" />
<property name="password" value="${datasource.password}" />
<property name="driverClassName" value="${datasource.driverClassName}" />
<property name="url" value="${datasource.url}" />
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="com.atguigu.entity">property>
<property name="configuration">
<bean class="org.apache.ibatis.session.Configuration">
<property name="mapUnderscoreToCamelCase" value="true"/>
bean>
property>
<property name="mapperLocations">
<array>
<value>classpath:mappers/*.xmlvalue>
array>
property>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<props>
<prop key="reasonable">trueprop>
<prop key="helperDialect">mysqlprop>
props>
property>
bean>
array>
property>
bean>
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.atguigu.mapper"/>
bean>
beans>
在resources目录中添加jdbc.properties
文件
datasource.username=root
datasource.password=123456
datasource.url=jdbc:mysql://localhost:3306/db_house?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
datasource.driverClassName=com.mysql.jdbc.Driver
创建映射配置文件存放文件夹:在resources目录添加:mappers文件夹
在resources/spring目录添加:spring-service.xml:
<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"
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">
<context:component-scan base-package="com.atguigu.service"/>
<import resource="classpath:spring/spring-persist.xml"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
beans>
在resources/spring目录添加:spring-mvc.xml
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.atguigu">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
context:component-scan>
<mvc:default-servlet-handler />
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8value>
<value>application/jsonvalue>
list>
property>
bean>
mvc:message-converters>
mvc:annotation-driven>
<bean id="templateResolver" class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/">property>
<property name="suffix" value=".html">property>
<property name="characterEncoding" value="UTF-8">property>
<property name="cacheable" value="false">property>
<property name="templateMode" value="LEGACYHTML5">property>
bean>
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="characterEncoding" value="UTF-8">property>
<property name="templateEngine" ref="templateEngine"/>
bean>
<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver">property>
bean>
beans>
<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">
<servlet>
<servlet-name>dispatcherServletservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring/spring-mvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>dispatcherServletservlet-name>
<url-pattern>/url-pattern>
servlet-mapping>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:spring/spring-service.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<filter>
<filter-name>CharacterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
<init-param>
<param-name>forceRequestEncodingparam-name>
<param-value>trueparam-value>
init-param>
<init-param>
<param-name>forceResponseEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>CharacterEncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
web-app>
我们用户角色为例,获取全部角色数据在页面显示。以下操作是在web-admin
工程中
在com.atguigu.mapper
包
package com.atguigu.mapper;
import com.atguigu.entity.Role;
import java.util.List;
public interface RoleMapper {
List<Role> findAll();
}
在resources/mappers
目录中
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mapper.RoleMapper">
<sql id="column">
select id,role_name,role_code,description,create_time,update_time,is_deleted
sql>
<select id="findAll" resultType="Role">
<include refid="column">include>
from acl_role
where is_deleted = 0
select>
mapper>
在com.atguigu.service
包
package com.atguigu.service;
import com.atguigu.entity.Role;
import java.util.List;
public interface RoleService {
List<Role> findAll();
}
在com.atguigu.service.impl
包
package com.atguigu.service.impl;
import com.atguigu.mapper.RoleMapper;
import com.atguigu.entity.Role;
import com.atguigu.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class RoleServiceImpl implements RoleService {
@Autowired
private RoleMapper roleMapper;
public List<Role> findAll() {
return roleMapper.findAll();
}
}
在com.atguigu.controller
包
package com.atguigu.controller;
import com.atguigu.entity.Role;
import com.atguigu.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping(value="/role")
public class RoleController {
@Autowired
private RoleService roleService;
private final static String PAGE_INDEX = "role/index";
/**
* 列表
* @param model
* @return
*/
@RequestMapping
public String index(Model model) {
List<Role> list = roleService.findAll();
model.addAttribute("list", list);
return PAGE_INDEX;
}
}
在WEB-INF/templates/role
目录中创建index.html
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<table>
<tr th:each="item,it : ${list}">
<td class="text-center" th:text="${it.count}">11td>
<td th:text="${item.roleName}">22td>
<td th:text="${item.roleCode}">33td>
<td th:text="${item.description}">33td>
<td th:text="${#dates.format(item.createTime,'yyyy-MM-dd HH:mm:ss')}" >33td>
tr>
table>
body>
html>
第一步:
第二步: