Maven+Dubbo+Mybatis+SpringBoot構建JavaWeb專案
SpringBoot靈活的配置減少了很多麻煩,首先要理解各個模組的作用。ZooKeeper是一個註冊中心,其中我們把呼叫了dao層的service層的實現給註冊到ZooKeeper中,然後在web呼叫rpc模組裡的service介面就可以使用service了。
首先建立一個數據庫,建一個user表,欄位包括id,username, password
1. 首先構建maven父專案,這裡我取名MyDemo,它包含3個子專案MyDemo-app(相當於dao層和service層)、MyDemo-rpc(包含資料傳輸物件dto和供web層呼叫的service介面)、MyDemo-web(Web專案)
父專案的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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.rambo</groupId> <artifactId>MyDemo</artifactId> <version>1.0</version> <packaging>pom</packaging> <dependencyManagement> <dependencies> <dependency> <!-- Import dependency management from Spring Boot --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.0.1.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- 一個減少冗餘程式碼的外掛 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <modules> <module>MyDemo-rpc</module> <module>MyDemo-app</module> <module>MyDemo-web</module> </modules> </project>
2. 建立MyDemo-app子模組,這裡用到了mybatis逆向工程生成domain和mapper檔案
①先寫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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>MyDemo-app</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>MyDemo-app</name> <description>Demo project for Spring Boot</description> <parent> <groupId>com.rambo</groupId> <artifactId>MyDemo</artifactId> <version>1.0</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>com.rambo</groupId> <artifactId>MyDemo-rpc</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.9</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.alibaba.spring.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.12</version> </dependency> <dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.5</version> <configuration> <configurationFile>src/main/resources/generatorConfig.xml</configurationFile> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> <dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency> </dependencies> </plugin> </plugins> </build> </project>
②寫mybatis的生成檔案:generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--執行generator外掛生成檔案的命令: call mvn mybatis-generator:generate -e -->
<!-- 引入配置檔案 -->
<!-- <properties resource="mybatis-generator/mybatisGeneratorinit.properties"/> -->
<!--classPathEntry:資料庫的JDBC驅動,換成你自己的驅動位置 可選 -->
<!--<classPathEntry location="D:\generator_mybatis\mysql-connector-java-5.1.24-bin.jar" /> -->
<!-- 一個數據庫一個context -->
<!--defaultModelType="flat" 大資料欄位,不分表 -->
<context id="context1">
<!-- 自動識別資料庫關鍵字,預設false,如果設定為true,根據SqlReservedWords中定義的關鍵字列表;
一般保留預設值,遇到資料庫關鍵字(Java關鍵字),使用columnOverride覆蓋 -->
<property name="autoDelimitKeywords" value="true" />
<!-- 生成的Java檔案的編碼 -->
<property name="javaFileEncoding" value="utf-8" />
<!-- beginningDelimiter和endingDelimiter:指明資料庫的用於標記資料庫物件名的符號,比如ORACLE就是雙引號,MYSQL預設是`反引號; -->
<property name="beginningDelimiter" value="`" />
<property name="endingDelimiter" value="`" />
<!-- 格式化java程式碼 -->
<property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
<!-- 格式化XML程式碼 -->
<property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>
<plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
<plugin type="org.mybatis.generator.plugins.ToStringPlugin" />
<commentGenerator>
<property name="suppressAllComments" value="true"/><!-- 是否取消註釋 -->
<property name="suppressDate" value="true" /> <!-- 是否生成註釋代時間戳-->
</commentGenerator>
<!-- jdbc連線 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/MyDemo?useUnicode=true&characterEncoding=utf-8"
userId="root" password="123456">
</jdbcConnection>
<!-- 型別轉換 -->
<javaTypeResolver>
<!-- 是否使用bigDecimal, false可自動轉化以下型別(Long, Integer, Short, etc.) -->
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- 生成的實體包路徑,包含實體類和Example類(用來定製sql的) -->
<javaModelGenerator targetPackage="com.rambo.MyDemo.app.domain"
targetProject="src/main/java" />
<!-- 生成的Mapper.xml路徑 -->
<sqlMapGenerator targetPackage="mybatis-mapping"
targetProject="src/main/resources" />
<!-- 生成的mapper類 -->
<javaClientGenerator targetPackage="com.rambo.MyDemo.app.dao"
targetProject="src/main/java" type="XMLMAPPER" />
<!-- table可以有多個,每個資料庫中的表都可以寫一個table,tableName表示要匹配的資料庫表,-->
<!-- 也可以在tableName屬性中通過使用%萬用字元來匹配所有資料庫表,只有匹配的表才會自動生成檔案 -->
<table schema="" tableName="user" domainObjectName="User"
enableCountByExample="true" enableUpdateByExample="true"
enableDeleteByExample="true" enableSelectByExample="true"
selectByExampleQueryId="true">
<property name="useActualColumnNames" value="false" />
<generatedKey column="id" sqlStatement="JDBC" identity="true" />
</table>
</context>
</generatorConfiguration>
③先maven->update project,然後maven build輸入mybatis-generator:generate生成domain和mapper等檔案
④建立application.yml配置資料庫和Dubbo
spring:
devtools:
livereload:
port: 35729
datasource:
url: jdbc:mysql://localhost:3306/MyDemo?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
druid:
filter:
config:
enabled: true
application:
name: dubbo-demo-provider
dubbo:
registry:
address: zookeeper://127.0.0.1:2181
server: true
protocol:
port: 20880
threadpool: cached
threads: 300
accepts: 500
serialization: java
mybatis:
mapperLocations: mybatis-mapping/**Mapper.xml
⑤建立MybatisConfiguration.java來掃描生成的mapper檔案
package com.rambo.MyDemo.app.config;
import javax.annotation.PostConstruct;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class, MybatisAutoConfiguration.class })
@MapperScan(MybatisConfiguration.BASE_MAPPER_PACKAGE)
public class MybatisConfiguration {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
protected static final String BASE_MAPPER_PACKAGE = "com.rambo.MyDemo.app.dao";
@PostConstruct
public void init() {
logger.info("載入" + BASE_MAPPER_PACKAGE + "路徑下的Mapper");
}
}
⑥建立啟動類
package com.rambo.MyDemo.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
@SpringBootApplication
@EnableDubboConfiguration
@EnableCaching
@EnableTransactionManagement
public class MyDemoAppApplication {
public static void main(String[] args) {
SpringApplication.run(MyDemoAppApplication.class, args);
}
}
3.建立MyDemo-rpc子模組maven專案,其作用是前端和後端的一個媒介以及web端呼叫service的介面
①pom.xml
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.rambo</groupId>
<artifactId>MyDemo</artifactId>
<version>1.0</version>
</parent>
<artifactId>MyDemo-rpc</artifactId>
<name>MyDemo-rpc</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
②建立dto物件,和生成的User一樣
③建立UserService介面
package com.rambo.MyDemo.rpc.iservice;
public interface UserService {
Object login(int userId, String password);
}
④在MyDemo-app模組裡實現UserService介面
package com.rambo.MyDemo.app.service;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.config.annotation.Service;
import com.rambo.MyDemo.app.dao.UserMapper;
import com.rambo.MyDemo.app.domain.User;
import com.rambo.MyDemo.app.domain.UserExample;
import com.rambo.MyDemo.app.domain.UserExample.Criteria;
import com.rambo.MyDemo.rpc.iservice.UserService;
@Service(interfaceClass=UserService.class)
@Component
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
public Object login(int userId, String password) {
UserExample userExample = new UserExample();
Criteria criteria = userExample.createCriteria();
criteria.andIdEqualTo(userId);
if (StringUtils.isNotEmpty(password)) {
criteria.andPasswordEqualTo(password);
}
List<User> userList = userMapper.selectByExample(userExample);
if (userList.size() > 0) {
User user = userList.get((0));
com.rambo.MyDemo.rpc.dto.User dtoUser = new com.rambo.MyDemo.rpc.dto.User();
BeanUtils.copyProperties(user, dtoUser);
return dtoUser;
}
return null;
}
}
4. 建立MyDemo-web子模組
1.編寫controller
package com.rambo.MyDemo.web.controller;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.dubbo.config.annotation.Reference;
import com.rambo.MyDemo.rpc.dto.User;
import com.rambo.MyDemo.rpc.iservice.UserService;
@RestController
public class LoginController {
@Reference
private UserService userService;
@RequestMapping(value = "/login",method = RequestMethod.POST)
public Map<String, String> adminlogin(HttpServletRequest request, User user) throws Exception {
User user1 = (User) userService.login(user.getId(), user.getPassword());
Map<String, String> map = new HashMap<String, String>();
if (user1 != null) {
HttpSession session = request.getSession(true);
session.setAttribute("user", user1);
map.put("message", "success");
map.put("name", user1.getName());
} else {
map.put("message", "fail");
}
return map;
}
@RequestMapping(value="/checkUser",method = RequestMethod.POST)
public String checkUser(HttpServletRequest request,HttpServletResponse response){
//編碼規範
response.setContentType("text/html;charset=utf-8");
response.setCharacterEncoding("utf-8");
//獲取session值
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
System.out.println(user.getName());
return user.getName();
}
}
②編寫配置檔案application.yml
spring:
devtools:
livereload:
port: 35728
application:
name: dubbo-demo-web
dubbo:
registry:
address: zookeeper://127.0.0.1:2181
protocol:
port: 20880
threadpool: cached
threads: 300
accepts: 500
serialization: java
cache:
redis:
key-prefix: dubbo-demo-provider-cache-
time-to-live: 10s
redis:
host: 127.0.0.1
port: 6379
timeout: 3s
mvc:
static-path-pattern: /**
resources:
static-locations: classpath:/META-INF/resources/,classpath:/resources/, classpath:/static/, classpath:/public/
shiro:
loginUrl: ${shiro.casServerUrlPrefix}?service=${shiro.webUrl}
successUrl: null
webUrl: http://127.0.0.1:8080/demo/shiro-cas
unauthorizedUrl: ${shiro.casServerUrlPrefix}?service=${shiro.webUrl}
casServerUrlPrefix: http://10.79.10.21:8080/cas
server:
port: 8080
servlet:
context-path: /MyDemo
③編寫前端頁面
<!DOCTYPE html>
<html lang="zh">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="../components/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../js/ajax.js"></script>
<script type="text/javascript" src="../common/js/store.min.js"></script>
</head>
<body>
<h3>登入頁面</h3>
<form >
<font color="red" >${requestScope.message}</font>
<table>
<tr>
<td><label>使用者ID:</label></td>
<td><input type="text" id="id" name="userId" value="1000"/></td>
</tr>
<tr>
<td><label>密碼:</label></td>
<td><input type="password" id="password" name="password" value="123456"/></td>
</tr>
<tr>
<td><button name="login" type="button" id="login" >登入</button></td>
</tr>
</table>
</form>
</body>
<script>
$(document).ready(function() {
$("#login").click(function() {
var userId = $("#id").val();
var password = $("#password").val();
console.log(userId+" "+password);
if (userId == "" || password == "") {
alert("使用者名稱和密碼不可以為空!");
} else {
var param = new Object();
param.id = userId;
param.password = password;
loginFun("../login", param);
}
});
});
function loginFun(urls,param) {
$.ajax({
type : "POST",
url : urls,
data : param,
dataType : "json",
contentType: "application/x-www-form-urlencoded",
success : function(data,textStatus,jqXHR) {
console.log(data,);
console.log(textStatus);
console.log(jqXHR);
if (data.message != "fail") {
alert("登陸成功");
window.location = 'home.html';
}else{
alert("賬號密碼錯誤");
}
}
});
}
</script>
</html>
④配置SPringBoot啟動類
package com.rambo.MyDemo.web;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cache.annotation.EnableCaching;
import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import com.rambo.MyDemo.web.DemoWebApplication;
@SpringBootApplication
@EnableDubboConfiguration
@EnableCaching
@ServletComponentScan
public class DemoWebApplication {
public static void main(String[] args) {
SpringApplication.run(DemoWebApplication.class, args);
}
}
執行先執行ZooKeeper,再以JavaAplication方式啟動MyDemo-app裡的類,再以SpringBoot方式啟動MyDemo-web裡的類,訪問localhost:8080/MyDemo/login.html即可