diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..249d5b2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,72 @@ +# Created by .ignore support plugin (hsz.mobi) +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +# Gradle: +.idea/**/gradle.xml +# CMake +cmake-build-debug/ + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties +### Java template +# Compiled class file +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# custom +*.iml + +**/target diff --git a/Dubbo-Demo/Service-Client/pom.xml b/Dubbo-Demo/Service-Client/pom.xml new file mode 100644 index 0000000..bac9551 --- /dev/null +++ b/Dubbo-Demo/Service-Client/pom.xml @@ -0,0 +1,14 @@ + + + + cn.mrdear.dubbo + Dubbo-Demo + 1.0.0 + + 4.0.0 + Service-Client + + + \ No newline at end of file diff --git a/Dubbo-Demo/Service-Client/src/main/java/cn/mrdear/client/dto/UserDTO.java b/Dubbo-Demo/Service-Client/src/main/java/cn/mrdear/client/dto/UserDTO.java new file mode 100644 index 0000000..72dd1ce --- /dev/null +++ b/Dubbo-Demo/Service-Client/src/main/java/cn/mrdear/client/dto/UserDTO.java @@ -0,0 +1,31 @@ +package cn.mrdear.client.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 用户DTO,用于Service层传输 + * @author Niu Li + * @since 2017/6/12 + */ +@Data +public class UserDTO implements Serializable{ + + private static final long serialVersionUID = 4086492518942464226L; + + private Long id; + + private String username; + + private String password; + + private Integer age; + + private String nickname; + + private String mail; + + private String memo; + +} diff --git a/Dubbo-Demo/Service-Client/src/main/java/cn/mrdear/client/service/IUserService.java b/Dubbo-Demo/Service-Client/src/main/java/cn/mrdear/client/service/IUserService.java new file mode 100644 index 0000000..1edd92f --- /dev/null +++ b/Dubbo-Demo/Service-Client/src/main/java/cn/mrdear/client/service/IUserService.java @@ -0,0 +1,37 @@ +package cn.mrdear.client.service; + +import cn.mrdear.client.dto.UserDTO; + +import java.util.Collection; +import java.util.List; + +/** + * 用户服务,一般都会在返回层再包裹一层,这里简而化之 + * @author Niu Li + * @since 2017/6/12 + */ +public interface IUserService { + + /** + * 根据id查找 + */ + UserDTO findById(Long id); + + /** + * 根据id批量查询 + */ + List queryByIds(Collection ids); + + /** + * 更新用户 + * @return 返回更新后的实体 + */ + UserDTO updateById(UserDTO userDTO); + + /** + * 根据id删除用户 + */ + Boolean deleteById(Long id); + + +} diff --git a/Dubbo-Demo/Service-Consumer/pom.xml b/Dubbo-Demo/Service-Consumer/pom.xml new file mode 100644 index 0000000..c8ba829 --- /dev/null +++ b/Dubbo-Demo/Service-Consumer/pom.xml @@ -0,0 +1,99 @@ + + + + cn.mrdear.dubbo + Dubbo-Demo + 1.0.0 + + war + 4.0.0 + Service-Consumer + + + + + cn.mrdear.dubbo + Service-Client + 1.0.0 + + + + com.netflix.hystrix + hystrix-javanica + 1.5.12 + + + + com.fasterxml.jackson.core + jackson-annotations + 2.8.1 + + + com.fasterxml.jackson.core + jackson-core + 2.8.6 + + + com.fasterxml.jackson.core + jackson-databind + 2.8.6 + + + + org.springframework + spring-context + 4.3.2.RELEASE + + + org.springframework + spring-webmvc + 4.3.2.RELEASE + + + + javax.servlet + jstl + 1.2 + runtime + + + org.springframework + spring-web + 4.3.2.RELEASE + + + org.springframework + spring-test + 4.3.2.RELEASE + + + + com.alibaba + dubbo + 2.5.3 + + + spring + org.springframework + + + + + com.101tec + zkclient + 0.10 + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + \ No newline at end of file diff --git a/Dubbo-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/controller/UserController.java b/Dubbo-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/controller/UserController.java new file mode 100644 index 0000000..9593c2d --- /dev/null +++ b/Dubbo-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/controller/UserController.java @@ -0,0 +1,27 @@ +package cn.mrdear.consumer.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import cn.mrdear.client.dto.UserDTO; +import cn.mrdear.consumer.manager.UserManager; + +import javax.annotation.Resource; + +/** + * @author Niu Li + * @since 2017/6/14 + */ +@RestController +public class UserController { + + @Resource + private UserManager userManager; + + @GetMapping("/user/{id}") + public UserDTO getUserById(@PathVariable Long id) { + UserDTO userDTO = userManager.findById(id); + return userDTO; + } +} diff --git a/Dubbo-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/manager/UserManager.java b/Dubbo-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/manager/UserManager.java new file mode 100644 index 0000000..900368e --- /dev/null +++ b/Dubbo-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/manager/UserManager.java @@ -0,0 +1,17 @@ +package cn.mrdear.consumer.manager; + +import cn.mrdear.client.dto.UserDTO; + +/** + * manager + * @author Niu Li + * @since 2017/6/13 + */ + +public interface UserManager { + + UserDTO findById(Long id); + + UserDTO findByIdBack(Long id); + +} diff --git a/Dubbo-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/manager/impl/UserManagerImpl.java b/Dubbo-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/manager/impl/UserManagerImpl.java new file mode 100644 index 0000000..572c407 --- /dev/null +++ b/Dubbo-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/manager/impl/UserManagerImpl.java @@ -0,0 +1,51 @@ +package cn.mrdear.consumer.manager.impl; + +import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; + +import org.springframework.stereotype.Service; + +import cn.mrdear.client.dto.UserDTO; +import cn.mrdear.client.service.IUserService; +import cn.mrdear.consumer.manager.UserManager; + +import javax.annotation.Resource; + +import java.util.Objects; + +/** + * manager调用远程RPC组装数据,此处调试只是再加一层封装 + * @author Niu Li + * @since 2017/6/13 + */ +@Service +public class UserManagerImpl implements UserManager { + + @Resource + private IUserService userService; + + @Override + @HystrixCommand(groupKey = "user", fallbackMethod = "findByIdBack") + public UserDTO findById(Long id) { + if (Objects.equals(id, 1L)) { + try { + Thread.sleep(1000000); + } catch (InterruptedException e) { + // do nothing + } + } + if (Objects.equals(id, 2L)) { + throw new RuntimeException("熔断测试"); + } + return userService.findById(id); + } + + public UserDTO findByIdBack(Long id) { + System.err.println("findByIdBack"); + UserDTO userDTO = new UserDTO(); + userDTO.setAge(1); + userDTO.setUsername("备用用户"); + return userDTO; + } + + +} diff --git a/Dubbo-Demo/Service-Consumer/src/main/resources/applicationContext.xml b/Dubbo-Demo/Service-Consumer/src/main/resources/applicationContext.xml new file mode 100644 index 0000000..4ddd015 --- /dev/null +++ b/Dubbo-Demo/Service-Consumer/src/main/resources/applicationContext.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Dubbo-Demo/Service-Consumer/src/main/resources/dispatcher-servlet.xml b/Dubbo-Demo/Service-Consumer/src/main/resources/dispatcher-servlet.xml new file mode 100644 index 0000000..9b9a484 --- /dev/null +++ b/Dubbo-Demo/Service-Consumer/src/main/resources/dispatcher-servlet.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Dubbo-Demo/Service-Consumer/src/main/webapp/WEB-INF/view/error.jsp b/Dubbo-Demo/Service-Consumer/src/main/webapp/WEB-INF/view/error.jsp new file mode 100644 index 0000000..e9ea535 --- /dev/null +++ b/Dubbo-Demo/Service-Consumer/src/main/webapp/WEB-INF/view/error.jsp @@ -0,0 +1,16 @@ +<%-- + Created by IntelliJ IDEA. + User: niuli + Date: 2017/4/19 + Time: 09:45 + To change this template use File | Settings | File Templates. +--%> +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Title + + +

Error 页面

+ + diff --git a/Dubbo-Demo/Service-Consumer/src/main/webapp/WEB-INF/web.xml b/Dubbo-Demo/Service-Consumer/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..f1339a6 --- /dev/null +++ b/Dubbo-Demo/Service-Consumer/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,65 @@ + + + + + + webAppRootKey + web.root + + + contextConfigLocation + classpath:applicationContext.xml + + + + + + encodingFilter + org.springframework.web.filter.CharacterEncodingFilter + + encoding + UTF-8 + + + + forceEncoding + true + + + + encodingFilter + /* + + + + org.springframework.web.util.WebAppRootListener + + + org.springframework.web.context.ContextLoaderListener + + + + org.springframework.web.util.IntrospectorCleanupListener + + + + + + dispatcher + org.springframework.web.servlet.DispatcherServlet + + contextConfigLocation + + classpath:dispatcher-servlet.xml + + 1 + + + dispatcher + / + + + diff --git a/Dubbo-Demo/Service-Consumer/src/main/webapp/index.jsp b/Dubbo-Demo/Service-Consumer/src/main/webapp/index.jsp new file mode 100644 index 0000000..fa47f72 --- /dev/null +++ b/Dubbo-Demo/Service-Consumer/src/main/webapp/index.jsp @@ -0,0 +1,17 @@ +<%-- + Created by IntelliJ IDEA. + User: NL + Date: 2017/1/23 + Time: 9:09 + To change this template use File | Settings | File Templates. +--%> +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + + + +

Hello World!

+

请访问/user/{id}测试

+ + diff --git a/Dubbo-Demo/Service-Consumer/src/test/java/cn/mrdear/test/UserManagerTest.java b/Dubbo-Demo/Service-Consumer/src/test/java/cn/mrdear/test/UserManagerTest.java new file mode 100644 index 0000000..bfe506b --- /dev/null +++ b/Dubbo-Demo/Service-Consumer/src/test/java/cn/mrdear/test/UserManagerTest.java @@ -0,0 +1,31 @@ +package cn.mrdear.test; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import cn.mrdear.client.dto.UserDTO; +import cn.mrdear.consumer.manager.UserManager; + +import javax.annotation.Resource; + +/** + * @author Niu Li + * @since 2017/6/13 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "classpath:applicationContext.xml") +public class UserManagerTest { + + @Resource + private UserManager userManager; + + + @Test + public void testFindById() { + UserDTO userDTO = userManager.findById(1L); + Assert.assertNotNull(userDTO); + } +} diff --git a/Dubbo-Demo/Service-Consumer/src/test/resources/applicationContext.xml b/Dubbo-Demo/Service-Consumer/src/test/resources/applicationContext.xml new file mode 100644 index 0000000..5a693f6 --- /dev/null +++ b/Dubbo-Demo/Service-Consumer/src/test/resources/applicationContext.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Dubbo-Demo/Service-Provider/pom.xml b/Dubbo-Demo/Service-Provider/pom.xml new file mode 100644 index 0000000..97f5cb5 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/pom.xml @@ -0,0 +1,120 @@ + + + + cn.mrdear.dubbo + Dubbo-Demo + 1.0.0 + + 4.0.0 + Service-Provider + + + + + cn.mrdear.dubbo + Service-Client + 1.0.0 + + + com.alibaba + dubbo + 2.5.3 + + + org.springframework + spring + + + org.javassist + javassist + + + + + com.101tec + zkclient + 0.10 + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + com.h2database + h2 + 1.4.187 + + + org.springframework + spring-context + 4.3.2.RELEASE + + + org.springframework + spring-test + 4.3.2.RELEASE + + + + org.aspectj + aspectjweaver + 1.8.6 + + + org.aspectj + aspectjrt + 1.8.6 + + + + + cglib + cglib + 3.2.2 + + + + + org.hibernate + hibernate-core + 5.1.0.Final + + + org.hibernate + hibernate-entitymanager + 5.1.0.Final + + + + + mysql + mysql-connector-java + 5.1.34 + + + + + com.alibaba + druid + 1.0.19 + + + + + + org.springframework.data + spring-data-jpa + 1.10.4.RELEASE + + + + + \ No newline at end of file diff --git a/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/Application.java b/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/Application.java new file mode 100644 index 0000000..cbebadb --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/Application.java @@ -0,0 +1,17 @@ +package cn.mrdear.provider; + +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import java.io.IOException; + +/** + * @author Niu Li + * @since 2017/6/12 + */ +public class Application { + public static void main(String[] args) throws IOException { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); + context.start(); + System.in.read(); // 为保证服务一直开着,利用输入流的阻塞来模拟 + } +} diff --git a/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/convert/UserConvert.java b/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/convert/UserConvert.java new file mode 100644 index 0000000..67ae9ca --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/convert/UserConvert.java @@ -0,0 +1,42 @@ +package cn.mrdear.provider.convert; + +import org.springframework.beans.BeanUtils; +import org.springframework.util.CollectionUtils; + +import cn.mrdear.client.dto.UserDTO; +import cn.mrdear.provider.domain.User; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Niu Li + * @since 2017/6/12 + */ +public class UserConvert { + + public static UserDTO toDTO(User user) { + UserDTO userDTO = new UserDTO(); + BeanUtils.copyProperties(user,userDTO); + return userDTO; + } + + + public static List toDTOS(List users) { + if (CollectionUtils.isEmpty(users)) { + return new ArrayList<>(1); + } + List results = new ArrayList<>(); + return users.stream().map(UserConvert::toDTO) + .collect(Collectors.toList()); + } + + + public static User toDO(UserDTO userDTO) { + User user = new User(); + BeanUtils.copyProperties(userDTO,user); + return user; + } + +} diff --git a/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/dao/UserRepository.java b/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/dao/UserRepository.java new file mode 100644 index 0000000..6b068b4 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/dao/UserRepository.java @@ -0,0 +1,24 @@ +package cn.mrdear.provider.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import cn.mrdear.provider.domain.User; + +import java.util.Collection; +import java.util.List; + +/** + * JPA repo层 + * @author Niu Li + * @since 2017/6/12 + */ +public interface UserRepository extends JpaRepository{ + + User findById(Long id); + + @Query("select p from User p where id in (?1)") + List queryByIds(Collection ids); + + +} diff --git a/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/domain/User.java b/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/domain/User.java new file mode 100644 index 0000000..81849e5 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/domain/User.java @@ -0,0 +1,39 @@ +package cn.mrdear.provider.domain; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +import java.io.Serializable; + +/** + * 用户实体类,对应数据库 + * @author Niu Li + * @since 2017/6/12 + */ +@Data +@Entity +@Table(name = "user") +public class User implements Serializable{ + + private static final long serialVersionUID = 1793488098966504793L; + @Id + @GeneratedValue + private Long id; + + private String username; + + private String password; + + private Integer age; + + private String nickname; + + private String mail; + + private String memo; + +} diff --git a/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/service/UserServiceImpl.java b/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/service/UserServiceImpl.java new file mode 100644 index 0000000..082f809 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/main/java/cn/mrdear/provider/service/UserServiceImpl.java @@ -0,0 +1,51 @@ +package cn.mrdear.provider.service; + +import com.alibaba.dubbo.config.annotation.Service; + +import cn.mrdear.client.dto.UserDTO; +import cn.mrdear.client.service.IUserService; +import cn.mrdear.provider.convert.UserConvert; +import cn.mrdear.provider.dao.UserRepository; +import cn.mrdear.provider.domain.User; + +import javax.annotation.Resource; + +import java.util.Collection; +import java.util.List; + +/** + * 用户服务的具体实现,作为服务提供方提供出去 + * @author Niu Li + * @since 2017/6/12 + */ +@Service(version = "1.0.0") +public class UserServiceImpl implements IUserService { + + @Resource + private UserRepository userRepository; + + @Override + public UserDTO findById(Long id) { + User user = userRepository.findById(id); + return UserConvert.toDTO(user); + } + + @Override + public List queryByIds(Collection ids) { + List users = userRepository.queryByIds(ids); + return UserConvert.toDTOS(users); + } + + @Override + public UserDTO updateById(UserDTO userDTO) { + User user = UserConvert.toDO(userDTO); + userRepository.save(user); + return this.findById(userDTO.getId()); + } + + @Override + public Boolean deleteById(Long id) { + userRepository.delete(id); + return true; + } +} diff --git a/Dubbo-Demo/Service-Provider/src/main/resources/applicationContext.xml b/Dubbo-Demo/Service-Provider/src/main/resources/applicationContext.xml new file mode 100644 index 0000000..c811fad --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/main/resources/applicationContext.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.hibernate.dialect.MySQL5Dialect + + false + + false + + false + + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Dubbo-Demo/Service-Provider/src/main/resources/db.properties b/Dubbo-Demo/Service-Provider/src/main/resources/db.properties new file mode 100644 index 0000000..2228684 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/main/resources/db.properties @@ -0,0 +1,24 @@ +jdbc.driver=com.mysql.jdbc.Driver +jdbc.url=jdbc:mysql://127.0.0.1:3306/ssm?useUnicode=true&characterEncoding=utf8&characterSetResults\ + =utf8 +jdbc.username=root +jdbc.password=7946521 + +filters:stat + +maxActive:20 +initialSize:1 +maxWait:60000 +minIdle:10 + +timeBetweenEvictionRunsMillis:60000 +minEvictableIdleTimeMillis:300000 + +testWhileIdle:true +testOnBorrow:false +testOnReturn:false + +maxOpenPreparedStatements:20 +removeAbandoned:true +removeAbandonedTimeout:1800 +logAbandoned:true diff --git a/Dubbo-Demo/Service-Provider/src/main/resources/h2/data.sql b/Dubbo-Demo/Service-Provider/src/main/resources/h2/data.sql new file mode 100644 index 0000000..a09f7a8 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/main/resources/h2/data.sql @@ -0,0 +1,6 @@ +INSERT INTO user (username, password, age, nickname, mail, memo) VALUES ('zhangsan', + '123456', 18, '张三', '1111@qq.com', 'hahahah'); +INSERT INTO user (username, password, age, nickname, mail, memo) VALUES ('lis', +'123456', 19, '李四', '123131@qq.com', 'xixiixxi'); +INSERT INTO user (username, password, age, nickname, mail, memo) VALUES ('wanger', +'123456', 29, '王二', '12131984@qq.com', 'dqdh'); \ No newline at end of file diff --git a/Dubbo-Demo/Service-Provider/src/main/resources/h2/schema.sql b/Dubbo-Demo/Service-Provider/src/main/resources/h2/schema.sql new file mode 100644 index 0000000..8de82c2 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/main/resources/h2/schema.sql @@ -0,0 +1,10 @@ +DROP TABLE user if exist; +create table user ( + id INT(11) AUTO_INCREMENT PRIMARY KEY , + username VARCHAR(255), + password VARCHAR(255), + age INT(3), + nickname VARCHAR(255), + mail VARCHAR(255), + memo VARCHAR(255), + ); \ No newline at end of file diff --git a/Dubbo-Demo/Service-Provider/src/main/resources/logback.xml b/Dubbo-Demo/Service-Provider/src/main/resources/logback.xml new file mode 100644 index 0000000..d68cd15 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + + + + %d{HH:mm:ss} [%t] %logger{5} [%line] %p - %msg%n + + + + + + + + + + + \ No newline at end of file diff --git a/Dubbo-Demo/Service-Provider/src/test/java/cn/mrdear/test/UserServiceTest.java b/Dubbo-Demo/Service-Provider/src/test/java/cn/mrdear/test/UserServiceTest.java new file mode 100644 index 0000000..3a50744 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/test/java/cn/mrdear/test/UserServiceTest.java @@ -0,0 +1,31 @@ +package cn.mrdear.test; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import cn.mrdear.client.dto.UserDTO; +import cn.mrdear.provider.service.UserServiceImpl; + +import javax.annotation.Resource; + +/** + * @author Niu Li + * @since 2017/6/13 + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "classpath:applicationContext.xml") +public class UserServiceTest { + + @Resource + private UserServiceImpl userService; + + @Test + public void testFindById() { + UserDTO userDTO = userService.findById(1L); + Assert.assertNotNull(userDTO); + } + +} diff --git a/Dubbo-Demo/Service-Provider/src/test/resources/applicationContext.xml b/Dubbo-Demo/Service-Provider/src/test/resources/applicationContext.xml new file mode 100644 index 0000000..0192b9b --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/test/resources/applicationContext.xml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.hibernate.dialect.MySQL5Dialect + + false + + false + + false + + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Dubbo-Demo/Service-Provider/src/test/resources/db.properties b/Dubbo-Demo/Service-Provider/src/test/resources/db.properties new file mode 100644 index 0000000..2228684 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/test/resources/db.properties @@ -0,0 +1,24 @@ +jdbc.driver=com.mysql.jdbc.Driver +jdbc.url=jdbc:mysql://127.0.0.1:3306/ssm?useUnicode=true&characterEncoding=utf8&characterSetResults\ + =utf8 +jdbc.username=root +jdbc.password=7946521 + +filters:stat + +maxActive:20 +initialSize:1 +maxWait:60000 +minIdle:10 + +timeBetweenEvictionRunsMillis:60000 +minEvictableIdleTimeMillis:300000 + +testWhileIdle:true +testOnBorrow:false +testOnReturn:false + +maxOpenPreparedStatements:20 +removeAbandoned:true +removeAbandonedTimeout:1800 +logAbandoned:true diff --git a/Dubbo-Demo/Service-Provider/src/test/resources/h2/data.sql b/Dubbo-Demo/Service-Provider/src/test/resources/h2/data.sql new file mode 100644 index 0000000..a09f7a8 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/test/resources/h2/data.sql @@ -0,0 +1,6 @@ +INSERT INTO user (username, password, age, nickname, mail, memo) VALUES ('zhangsan', + '123456', 18, '张三', '1111@qq.com', 'hahahah'); +INSERT INTO user (username, password, age, nickname, mail, memo) VALUES ('lis', +'123456', 19, '李四', '123131@qq.com', 'xixiixxi'); +INSERT INTO user (username, password, age, nickname, mail, memo) VALUES ('wanger', +'123456', 29, '王二', '12131984@qq.com', 'dqdh'); \ No newline at end of file diff --git a/Dubbo-Demo/Service-Provider/src/test/resources/h2/schema.sql b/Dubbo-Demo/Service-Provider/src/test/resources/h2/schema.sql new file mode 100644 index 0000000..8de82c2 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/test/resources/h2/schema.sql @@ -0,0 +1,10 @@ +DROP TABLE user if exist; +create table user ( + id INT(11) AUTO_INCREMENT PRIMARY KEY , + username VARCHAR(255), + password VARCHAR(255), + age INT(3), + nickname VARCHAR(255), + mail VARCHAR(255), + memo VARCHAR(255), + ); \ No newline at end of file diff --git a/Dubbo-Demo/Service-Provider/src/test/resources/logback.xml b/Dubbo-Demo/Service-Provider/src/test/resources/logback.xml new file mode 100644 index 0000000..d68cd15 --- /dev/null +++ b/Dubbo-Demo/Service-Provider/src/test/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + + + + %d{HH:mm:ss} [%t] %logger{5} [%line] %p - %msg%n + + + + + + + + + + + \ No newline at end of file diff --git a/Dubbo-Demo/doc/readme.md b/Dubbo-Demo/doc/readme.md new file mode 100644 index 0000000..47335f0 --- /dev/null +++ b/Dubbo-Demo/doc/readme.md @@ -0,0 +1,7 @@ + +1. 启动需要先下载zk,然后启动 +2. Provider中spring配置文件host改成本机ip地址,然后启动 +3. 启动Consumer +4. 可下载Simple-monitor http://download.csdn.net/detail/liweifengwf/7864009 +5. 可下载dubbo-admin http://download.csdn.net/detail/leiyong0326/9548973 +6. dubbo的调用基本就是这样,大多数规则都可以在admin中配置也可以在spring注册服务和引用的时候配置 \ No newline at end of file diff --git a/Dubbo-Demo/pom.xml b/Dubbo-Demo/pom.xml new file mode 100644 index 0000000..bd21a12 --- /dev/null +++ b/Dubbo-Demo/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + cn.mrdear.dubbo + Dubbo-Demo + pom + 1.0.0 + Dubbo-demo + + Service-Client + Service-Consumer + Service-Provider + + + + + + org.projectlombok + lombok + 1.16.14 + + + junit + junit + 4.12 + + + com.google.guava + guava + 21.0 + + + + org.slf4j + slf4j-api + 1.7.7 + + + org.slf4j + jcl-over-slf4j + 1.7.7 + + + ch.qos.logback + logback-core + 1.1.2 + + + org.logback-extensions + logback-ext-spring + 0.1.4 + + + ch.qos.logback + logback-classic + 1.1.2 + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + UTF-8 + + + + + + \ No newline at end of file diff --git a/Motan-Demo/Service-Client/pom.xml b/Motan-Demo/Service-Client/pom.xml new file mode 100644 index 0000000..8d2eade --- /dev/null +++ b/Motan-Demo/Service-Client/pom.xml @@ -0,0 +1,16 @@ + + + + Motan-Demo + cn.mrdear.motan + 1.0-SNAPSHOT + + 4.0.0 + + cn.mrdear.motan + Service-Client + + + \ No newline at end of file diff --git a/Motan-Demo/Service-Client/src/main/java/cn/mrdear/client/dto/UserDTO.java b/Motan-Demo/Service-Client/src/main/java/cn/mrdear/client/dto/UserDTO.java new file mode 100644 index 0000000..72dd1ce --- /dev/null +++ b/Motan-Demo/Service-Client/src/main/java/cn/mrdear/client/dto/UserDTO.java @@ -0,0 +1,31 @@ +package cn.mrdear.client.dto; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 用户DTO,用于Service层传输 + * @author Niu Li + * @since 2017/6/12 + */ +@Data +public class UserDTO implements Serializable{ + + private static final long serialVersionUID = 4086492518942464226L; + + private Long id; + + private String username; + + private String password; + + private Integer age; + + private String nickname; + + private String mail; + + private String memo; + +} diff --git a/Motan-Demo/Service-Client/src/main/java/cn/mrdear/client/service/IUserService.java b/Motan-Demo/Service-Client/src/main/java/cn/mrdear/client/service/IUserService.java new file mode 100644 index 0000000..1edd92f --- /dev/null +++ b/Motan-Demo/Service-Client/src/main/java/cn/mrdear/client/service/IUserService.java @@ -0,0 +1,37 @@ +package cn.mrdear.client.service; + +import cn.mrdear.client.dto.UserDTO; + +import java.util.Collection; +import java.util.List; + +/** + * 用户服务,一般都会在返回层再包裹一层,这里简而化之 + * @author Niu Li + * @since 2017/6/12 + */ +public interface IUserService { + + /** + * 根据id查找 + */ + UserDTO findById(Long id); + + /** + * 根据id批量查询 + */ + List queryByIds(Collection ids); + + /** + * 更新用户 + * @return 返回更新后的实体 + */ + UserDTO updateById(UserDTO userDTO); + + /** + * 根据id删除用户 + */ + Boolean deleteById(Long id); + + +} diff --git a/Motan-Demo/Service-Consumer/pom.xml b/Motan-Demo/Service-Consumer/pom.xml new file mode 100644 index 0000000..31ec032 --- /dev/null +++ b/Motan-Demo/Service-Consumer/pom.xml @@ -0,0 +1,108 @@ + + + + Motan-Demo + cn.mrdear.motan + 1.0-SNAPSHOT + + 4.0.0 + + cn.mrdear.motan + Service-Consumer + + + + cn.mrdear.motan + Service-Client + 1.0-SNAPSHOT + + + + com.weibo + motan-core + RELEASE + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + com.weibo + motan-transport-netty + RELEASE + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + com.weibo + motan-registry-zookeeper + RELEASE + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + com.101tec + zkclient + + + + + com.101tec + zkclient + 0.10 + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + com.weibo + motan-springsupport + RELEASE + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + org.springframework + spring-context + 4.3.6.RELEASE + + + + \ No newline at end of file diff --git a/Motan-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/ApplicationStart.java b/Motan-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/ApplicationStart.java new file mode 100644 index 0000000..f5e634b --- /dev/null +++ b/Motan-Demo/Service-Consumer/src/main/java/cn/mrdear/consumer/ApplicationStart.java @@ -0,0 +1,21 @@ +package cn.mrdear.consumer; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import cn.mrdear.client.service.IUserService; + +/** + * @author Niu Li + * @since 2017/6/14 + */ +public class ApplicationStart { + + public static void main(String[] args) throws InterruptedException { + ApplicationContext ctx = new ClassPathXmlApplicationContext( + "classpath:applicationContext.xml"); + IUserService service = (IUserService) ctx.getBean("userService"); + System.out.println(service.findById(1L)); + } + +} diff --git a/Motan-Demo/Service-Consumer/src/main/resources/applicationContext.xml b/Motan-Demo/Service-Consumer/src/main/resources/applicationContext.xml new file mode 100644 index 0000000..28b860c --- /dev/null +++ b/Motan-Demo/Service-Consumer/src/main/resources/applicationContext.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Motan-Demo/Service-Consumer/src/main/resources/logback.xml b/Motan-Demo/Service-Consumer/src/main/resources/logback.xml new file mode 100644 index 0000000..d68cd15 --- /dev/null +++ b/Motan-Demo/Service-Consumer/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + + + + %d{HH:mm:ss} [%t] %logger{5} [%line] %p - %msg%n + + + + + + + + + + + \ No newline at end of file diff --git a/Motan-Demo/Service-Provider/pom.xml b/Motan-Demo/Service-Provider/pom.xml new file mode 100644 index 0000000..d5a727e --- /dev/null +++ b/Motan-Demo/Service-Provider/pom.xml @@ -0,0 +1,151 @@ + + + + Motan-Demo + cn.mrdear.motan + 1.0-SNAPSHOT + + 4.0.0 + + cn.mrdear.motan + Service-Provider + + + + + cn.mrdear.motan + Service-Client + 1.0-SNAPSHOT + + + + com.weibo + motan-core + RELEASE + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + com.weibo + motan-transport-netty + RELEASE + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + com.weibo + motan-registry-zookeeper + RELEASE + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + com.101tec + zkclient + + + + + com.101tec + zkclient + 0.10 + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + + com.weibo + motan-springsupport + RELEASE + + + log4j + log4j + + + org.slf4j + slf4j-log4j12 + + + + + org.springframework + spring-context + 4.3.6.RELEASE + + + org.springframework.data + spring-data-jpa + 1.10.4.RELEASE + + + + org.hibernate + hibernate-core + 5.1.0.Final + + + org.hibernate + hibernate-entitymanager + 5.1.0.Final + + + + + org.aspectj + aspectjweaver + 1.8.6 + + + org.aspectj + aspectjrt + 1.8.6 + + + + + cglib + cglib + 3.2.2 + + + + com.h2database + h2 + 1.4.187 + + + + \ No newline at end of file diff --git a/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/ApplicationStart.java b/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/ApplicationStart.java new file mode 100644 index 0000000..7db2920 --- /dev/null +++ b/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/ApplicationStart.java @@ -0,0 +1,22 @@ +package cn.mrdear.provider; + +import com.weibo.api.motan.common.MotanConstants; +import com.weibo.api.motan.util.MotanSwitcherUtil; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author Niu Li + * @since 2017/6/14 + */ +public class ApplicationStart { + + public static void main(String[] args) throws InterruptedException { + ApplicationContext applicationContext = + new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); + MotanSwitcherUtil.setSwitcherValue(MotanConstants.REGISTRY_HEARTBEAT_SWITCHER, true); + System.out.println("server start..."); + } + +} diff --git a/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/convert/UserConvert.java b/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/convert/UserConvert.java new file mode 100644 index 0000000..67ae9ca --- /dev/null +++ b/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/convert/UserConvert.java @@ -0,0 +1,42 @@ +package cn.mrdear.provider.convert; + +import org.springframework.beans.BeanUtils; +import org.springframework.util.CollectionUtils; + +import cn.mrdear.client.dto.UserDTO; +import cn.mrdear.provider.domain.User; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Niu Li + * @since 2017/6/12 + */ +public class UserConvert { + + public static UserDTO toDTO(User user) { + UserDTO userDTO = new UserDTO(); + BeanUtils.copyProperties(user,userDTO); + return userDTO; + } + + + public static List toDTOS(List users) { + if (CollectionUtils.isEmpty(users)) { + return new ArrayList<>(1); + } + List results = new ArrayList<>(); + return users.stream().map(UserConvert::toDTO) + .collect(Collectors.toList()); + } + + + public static User toDO(UserDTO userDTO) { + User user = new User(); + BeanUtils.copyProperties(userDTO,user); + return user; + } + +} diff --git a/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/dao/UserRepository.java b/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/dao/UserRepository.java new file mode 100644 index 0000000..6b068b4 --- /dev/null +++ b/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/dao/UserRepository.java @@ -0,0 +1,24 @@ +package cn.mrdear.provider.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import cn.mrdear.provider.domain.User; + +import java.util.Collection; +import java.util.List; + +/** + * JPA repo层 + * @author Niu Li + * @since 2017/6/12 + */ +public interface UserRepository extends JpaRepository{ + + User findById(Long id); + + @Query("select p from User p where id in (?1)") + List queryByIds(Collection ids); + + +} diff --git a/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/domain/User.java b/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/domain/User.java new file mode 100644 index 0000000..81849e5 --- /dev/null +++ b/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/domain/User.java @@ -0,0 +1,39 @@ +package cn.mrdear.provider.domain; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +import java.io.Serializable; + +/** + * 用户实体类,对应数据库 + * @author Niu Li + * @since 2017/6/12 + */ +@Data +@Entity +@Table(name = "user") +public class User implements Serializable{ + + private static final long serialVersionUID = 1793488098966504793L; + @Id + @GeneratedValue + private Long id; + + private String username; + + private String password; + + private Integer age; + + private String nickname; + + private String mail; + + private String memo; + +} diff --git a/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/service/UserServiceImpl.java b/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/service/UserServiceImpl.java new file mode 100644 index 0000000..7ab049a --- /dev/null +++ b/Motan-Demo/Service-Provider/src/main/java/cn/mrdear/provider/service/UserServiceImpl.java @@ -0,0 +1,46 @@ +package cn.mrdear.provider.service; + +import cn.mrdear.client.dto.UserDTO; +import cn.mrdear.client.service.IUserService; +import cn.mrdear.provider.convert.UserConvert; +import cn.mrdear.provider.dao.UserRepository; +import cn.mrdear.provider.domain.User; + +import javax.annotation.Resource; + +import java.util.Collection; +import java.util.List; + +/** + * @author Niu Li + * @since 2017/6/14 + */ +public class UserServiceImpl implements IUserService{ + @Resource + private UserRepository userRepository; + + @Override + public UserDTO findById(Long id) { + User user = userRepository.findById(id); + return UserConvert.toDTO(user); + } + + @Override + public List queryByIds(Collection ids) { + List users = userRepository.queryByIds(ids); + return UserConvert.toDTOS(users); + } + + @Override + public UserDTO updateById(UserDTO userDTO) { + User user = UserConvert.toDO(userDTO); + userRepository.save(user); + return this.findById(userDTO.getId()); + } + + @Override + public Boolean deleteById(Long id) { + userRepository.delete(id); + return true; + } +} diff --git a/Motan-Demo/Service-Provider/src/main/resources/applicationContext.xml b/Motan-Demo/Service-Provider/src/main/resources/applicationContext.xml new file mode 100644 index 0000000..4b5d788 --- /dev/null +++ b/Motan-Demo/Service-Provider/src/main/resources/applicationContext.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.hibernate.dialect.MySQL5Dialect + + false + + false + + false + + none + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Motan-Demo/Service-Provider/src/main/resources/h2/data.sql b/Motan-Demo/Service-Provider/src/main/resources/h2/data.sql new file mode 100644 index 0000000..a09f7a8 --- /dev/null +++ b/Motan-Demo/Service-Provider/src/main/resources/h2/data.sql @@ -0,0 +1,6 @@ +INSERT INTO user (username, password, age, nickname, mail, memo) VALUES ('zhangsan', + '123456', 18, '张三', '1111@qq.com', 'hahahah'); +INSERT INTO user (username, password, age, nickname, mail, memo) VALUES ('lis', +'123456', 19, '李四', '123131@qq.com', 'xixiixxi'); +INSERT INTO user (username, password, age, nickname, mail, memo) VALUES ('wanger', +'123456', 29, '王二', '12131984@qq.com', 'dqdh'); \ No newline at end of file diff --git a/Motan-Demo/Service-Provider/src/main/resources/h2/schema.sql b/Motan-Demo/Service-Provider/src/main/resources/h2/schema.sql new file mode 100644 index 0000000..8de82c2 --- /dev/null +++ b/Motan-Demo/Service-Provider/src/main/resources/h2/schema.sql @@ -0,0 +1,10 @@ +DROP TABLE user if exist; +create table user ( + id INT(11) AUTO_INCREMENT PRIMARY KEY , + username VARCHAR(255), + password VARCHAR(255), + age INT(3), + nickname VARCHAR(255), + mail VARCHAR(255), + memo VARCHAR(255), + ); \ No newline at end of file diff --git a/Motan-Demo/Service-Provider/src/main/resources/logback.xml b/Motan-Demo/Service-Provider/src/main/resources/logback.xml new file mode 100644 index 0000000..d68cd15 --- /dev/null +++ b/Motan-Demo/Service-Provider/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + + + + %d{HH:mm:ss} [%t] %logger{5} [%line] %p - %msg%n + + + + + + + + + + + \ No newline at end of file diff --git a/Motan-Demo/pom.xml b/Motan-Demo/pom.xml new file mode 100644 index 0000000..eb68369 --- /dev/null +++ b/Motan-Demo/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + pom + + + Service-Client + Service-Provider + Service-Consumer + + + cn.mrdear.motan + Motan-Demo + 1.0-SNAPSHOT + + + + + org.projectlombok + lombok + 1.16.14 + + + junit + junit + 4.12 + + + com.google.guava + guava + 21.0 + + + + org.slf4j + slf4j-api + 1.7.7 + + + org.slf4j + jcl-over-slf4j + 1.7.7 + + + ch.qos.logback + logback-core + 1.1.2 + + + org.logback-extensions + logback-ext-spring + 0.1.4 + + + ch.qos.logback + logback-classic + 1.1.2 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + UTF-8 + + + + + + \ No newline at end of file diff --git a/README.MD b/README.MD index e9d7053..5ab30da 100644 --- a/README.MD +++ b/README.MD @@ -1,3 +1,7 @@ +### 2017.9.27 +随着开发经验的增加,现在觉得这种Demo对于学习一个框架起不到太大的作用,顶多是个参考,并且由于使用经验的增加,对于之前一些错误的用法很难得到纠正,如果想要快速入门的话官方+造轮子才是最佳选择,类似豆瓣有许多开放的API,都可以用来练手,最后该项目不再更新,这点经验希望能帮助你. + + #该仓库主要记录学习javaWEB中一些Demo 1.SSM-Demo @@ -55,5 +59,17 @@ SpringDataRedis学习的一个Demo,内容不多,配合博文:[redis学习记录( -------------- 学习Spring Cloud的一个Demo,其中对于Eureka,Ribbon,Feign等都有相应的Demo,相应博文会更新在[我的博客](mrdear.cn)上,希望对你有帮助 -13.待添加 +13.Dubbo-Demo +-------------- +增加Dubbo-Demo,一个基本的RPC调用Demo + +14.Motan-Demo +-------------- +增加Motan-Demo,一个基本的RPC调用Demo + +15.Spring-Security-Demo +-------------- +增加Spring Security Demo,项目中使用了JWT Token验证机制,该项目可以很好的了解整个流程的作用,需要配合我博客中Spring Security相关博文食用. + +16.待添加 -------------- diff --git a/Spring-Cloud-Demo/Service-User-Provider/target/classes/cn/mrdear/Application.class b/Spring-Cloud-Demo/Service-User-Provider/target/classes/cn/mrdear/Application.class new file mode 100644 index 0000000..0625b42 Binary files /dev/null and b/Spring-Cloud-Demo/Service-User-Provider/target/classes/cn/mrdear/Application.class differ diff --git a/Spring-Security-Demo/pom.xml b/Spring-Security-Demo/pom.xml new file mode 100644 index 0000000..034f981 --- /dev/null +++ b/Spring-Security-Demo/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + + cn.mrdear.security + Spring-Security-Demo + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.5.4.RELEASE + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + io.jsonwebtoken + jjwt + 0.7.0 + + + org.projectlombok + lombok + + + org.apache.commons + commons-lang3 + 3.5 + + + com.google.guava + guava + 21.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + \ No newline at end of file diff --git a/Spring-Security-Demo/src/main/java/cn/mrdear/security/Application.java b/Spring-Security-Demo/src/main/java/cn/mrdear/security/Application.java new file mode 100644 index 0000000..a8425d5 --- /dev/null +++ b/Spring-Security-Demo/src/main/java/cn/mrdear/security/Application.java @@ -0,0 +1,17 @@ +package cn.mrdear.security; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author Niu Li + * @since 2017/6/16 + */ +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/CommonBeanConfig.java b/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/CommonBeanConfig.java new file mode 100644 index 0000000..bc1958e --- /dev/null +++ b/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/CommonBeanConfig.java @@ -0,0 +1,23 @@ +package cn.mrdear.security.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import cn.mrdear.security.util.JwtTokenUtil; + +/** + * 配置一些线程安全的工具类 + * @author Niu Li + * @since 2017/6/28 + */ +@Configuration +public class CommonBeanConfig { + + /** + * 配置jwt token + */ + @Bean + public JwtTokenUtil configToken() { + return new JwtTokenUtil(); + } +} diff --git a/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/CorsFilter.java b/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/CorsFilter.java new file mode 100644 index 0000000..2babd09 --- /dev/null +++ b/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/CorsFilter.java @@ -0,0 +1,40 @@ +package cn.mrdear.security.config; + +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.IOException; + + +public class CorsFilter implements javax.servlet.Filter { + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + System.err.println("CorsFilter"); + HttpServletResponse res = (HttpServletResponse) response; + HttpServletRequest req = (HttpServletRequest) request; + + res.setHeader("Access-Control-Allow-Origin", "*"); + res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS"); + res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, Referer, Connection, User-Agent, authorization, sw-useragent, sw-version"); + + // Just REPLY OK if request method is OPTIONS for CORS (pre-flight) + if (req.getMethod().equals("OPTIONS")) { + res.setStatus(HttpServletResponse.SC_OK); + return; + } + chain.doFilter(request, response); + } + + @Override + public void destroy() { + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } +} diff --git a/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/SecurityConfig.java b/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/SecurityConfig.java new file mode 100644 index 0000000..0c7f13a --- /dev/null +++ b/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/SecurityConfig.java @@ -0,0 +1,64 @@ +package cn.mrdear.security.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.access.channel.ChannelProcessingFilter; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.context.NullSecurityContextRepository; + +import cn.mrdear.security.util.JwtTokenUtil; + +import javax.annotation.Resource; + +/** + * Spring Security配置类 + * @author Niu Li + * @since 2017/6/16 + */ +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Resource + private JwtTokenUtil jwtTokenUtil; + + /** + * 在此配置不过滤的请求 + */ + @Override + public void configure(WebSecurity web) throws Exception { + //每一个请求对应一个空的filter链,这里一般不要配置过多, + // 因为查找处是一个for循环,过多就导致每个请求都需要循环一遍直到找到 + web.ignoring().antMatchers("/","/login","/favicon.ico"); + } + + /** + * 在此配置过滤链 + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + //角色定义,Spring Security会在其前面自动加上ROLE_,因此存储权限的时候也要加上ROLE_ADMIN + .antMatchers("/detail").access("hasRole('ADMIN')") + .anyRequest().permitAll().and() + //异常处理,可以再此使用entrypoint来定义错误输出 + .exceptionHandling().and() + //不需要session来控制,所以这里可以去掉 + .securityContext().securityContextRepository(new NullSecurityContextRepository()).and() + //开启匿名访问 + .anonymous().and() + //退出登录自己来控制 + .logout().disable() + //因为没用到cookies,所以关闭cookies + .csrf().disable() + //允许跨域 + .addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class) + //验证token + .addFilterBefore(new VerifyTokenFilter(jwtTokenUtil), + UsernamePasswordAuthenticationFilter.class); + } +} diff --git a/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/VerifyTokenFilter.java b/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/VerifyTokenFilter.java new file mode 100644 index 0000000..2054617 --- /dev/null +++ b/Spring-Security-Demo/src/main/java/cn/mrdear/security/config/VerifyTokenFilter.java @@ -0,0 +1,46 @@ +package cn.mrdear.security.config; + +import lombok.extern.slf4j.Slf4j; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import cn.mrdear.security.util.JwtTokenUtil; +import io.jsonwebtoken.JwtException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import java.io.IOException; +import java.util.Optional; + +/** + * jwt token验证类,验证成功后设置进去SecurityContext中 + * @author Niu Li + * @since 2017/6/28 + */ +@Slf4j +public class VerifyTokenFilter extends OncePerRequestFilter { + + private JwtTokenUtil jwtTokenUtil; + + public VerifyTokenFilter(JwtTokenUtil jwtTokenUtil) { + this.jwtTokenUtil = jwtTokenUtil; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + try { + Optional authentication = jwtTokenUtil.verifyToken(request); + log.debug("VerifyTokenFilter result: {}",authentication.orElse(null)); + SecurityContextHolder.getContext().setAuthentication(authentication.orElse(null)); + filterChain.doFilter(request,response); + } catch (JwtException e) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + //可以在这里指定重定向还是返回错误接口示例 + } + } +} diff --git a/Spring-Security-Demo/src/main/java/cn/mrdear/security/controller/LoginCntroller.java b/Spring-Security-Demo/src/main/java/cn/mrdear/security/controller/LoginCntroller.java new file mode 100644 index 0000000..488fc57 --- /dev/null +++ b/Spring-Security-Demo/src/main/java/cn/mrdear/security/controller/LoginCntroller.java @@ -0,0 +1,65 @@ +package cn.mrdear.security.controller; + +import com.google.common.collect.Lists; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import cn.mrdear.security.dto.TokenUserDTO; +import cn.mrdear.security.util.JwtTokenUtil; + +import javax.annotation.Resource; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * @author Niu Li + * @since 2017/6/19 + */ +@RestController +public class LoginCntroller { + + @Resource + private JwtTokenUtil jwtTokenUtil; + + /** + * 该链接获取token + */ + @GetMapping("/login") + public Map login(String username, String password) { + Map map = new HashMap<>(); + if (!StringUtils.equals(username, "demo") || !StringUtils.equals(password, "demo")) { + map.put("status", 4); + map.put("msg", "登录失败,用户名密码错误"); + return map; + } + TokenUserDTO userDTO = new TokenUserDTO(); + userDTO.setUsername(username); + userDTO.setRoles(Lists.newArrayList("ROLE_ADMIN")); + userDTO.setId(1L); + userDTO.setEmail("1015315668@qq.com"); + userDTO.setAvatar("ahahhahahhaha"); + map.put("status", 1); + map.put("msg", "Success"); + map.put("token", jwtTokenUtil.create(userDTO)); + return map; + } + + /** + * 该链接尝试获取登录用户,返回该认证用户的信息,请求该链接需要在header中放入x-authorization: token + */ + @GetMapping("/detail") + public TokenUserDTO userDetail() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (Objects.isNull(authentication)) { + return null; + } + return (TokenUserDTO) authentication.getDetails(); + } + +} diff --git a/Spring-Security-Demo/src/main/java/cn/mrdear/security/dto/TokenUserAuthentication.java b/Spring-Security-Demo/src/main/java/cn/mrdear/security/dto/TokenUserAuthentication.java new file mode 100644 index 0000000..188acfc --- /dev/null +++ b/Spring-Security-Demo/src/main/java/cn/mrdear/security/dto/TokenUserAuthentication.java @@ -0,0 +1,63 @@ +package cn.mrdear.security.dto; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; + +import java.util.Collection; +import java.util.stream.Collectors; + +/** + * Spring Security中存放的认证用户 + * @author Niu Li + * @since 2017/6/28 + */ +public class TokenUserAuthentication implements Authentication { + + private static final long serialVersionUID = 3730332217518791533L; + + private TokenUserDTO userDTO; + + private Boolean authentication = false; + + public TokenUserAuthentication(TokenUserDTO userDTO, Boolean authentication) { + this.userDTO = userDTO; + this.authentication = authentication; + } + + @Override + public Collection getAuthorities() { + return userDTO.getRoles().stream() + .map(SimpleGrantedAuthority::new).collect(Collectors.toList()); + } + + @Override + public Object getCredentials() { + return ""; + } + + @Override + public Object getDetails() { + return userDTO; + } + + @Override + public Object getPrincipal() { + return userDTO.getUsername(); + } + + @Override + public boolean isAuthenticated() { + return authentication; + } + + @Override + public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { + this.authentication = isAuthenticated; + } + + @Override + public String getName() { + return userDTO.getUsername(); + } +} diff --git a/Spring-Security-Demo/src/main/java/cn/mrdear/security/dto/TokenUserDTO.java b/Spring-Security-Demo/src/main/java/cn/mrdear/security/dto/TokenUserDTO.java new file mode 100644 index 0000000..a7abda4 --- /dev/null +++ b/Spring-Security-Demo/src/main/java/cn/mrdear/security/dto/TokenUserDTO.java @@ -0,0 +1,23 @@ +package cn.mrdear.security.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author Niu Li + * @since 2017/6/28 + */ +@Data +public class TokenUserDTO { + + private Long id; + + private String username; + + private String email; + + private String avatar; + + private List roles; +} diff --git a/Spring-Security-Demo/src/main/java/cn/mrdear/security/util/JwtTokenUtil.java b/Spring-Security-Demo/src/main/java/cn/mrdear/security/util/JwtTokenUtil.java new file mode 100644 index 0000000..91fcecc --- /dev/null +++ b/Spring-Security-Demo/src/main/java/cn/mrdear/security/util/JwtTokenUtil.java @@ -0,0 +1,91 @@ +package cn.mrdear.security.util; + +import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.Authentication; + +import cn.mrdear.security.dto.TokenUserAuthentication; +import cn.mrdear.security.dto.TokenUserDTO; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +import javax.servlet.http.HttpServletRequest; + +import java.util.Date; +import java.util.List; +import java.util.Optional; + +/** + * jwt token + * + * @author Niu Li + * @since 2017/6/28 + */ +public class JwtTokenUtil { + /** + * token过期时间 + */ + private static final long VALIDITY_TIME_MS = 24 * 60 * 60 * 1000; // 24 hours validity + /** + * header中标识 + */ + private static final String AUTH_HEADER_NAME = "x-authorization"; + + /** + * 签名密钥 + */ + @Value("${jwt.token.secret}") + private String secret; + + /** + * 验签 + */ + public Optional verifyToken(HttpServletRequest request) { + final String token = request.getHeader(AUTH_HEADER_NAME); + if (token != null && !token.isEmpty()){ + final TokenUserDTO user = parse(token.trim()); + if (user != null) { + return Optional.of(new TokenUserAuthentication(user, true)); + } + } + return Optional.empty(); + } + + + /** + * 从用户中创建一个jwt Token + * + * @param userDTO 用户 + * @return token + */ + public String create(TokenUserDTO userDTO) { + return Jwts.builder() + .setExpiration(new Date(System.currentTimeMillis() + VALIDITY_TIME_MS)) + .setSubject(userDTO.getUsername()) + .claim("id", userDTO.getId()) + .claim("avatar", userDTO.getAvatar()) + .claim("email", userDTO.getEmail()) + .claim("roles", userDTO.getRoles()) + .signWith(SignatureAlgorithm.HS256, secret) + .compact(); + } + + /** + * 从token中取出用户 + */ + public TokenUserDTO parse(String token) { + Claims claims = Jwts.parser() + .setSigningKey(secret) + .parseClaimsJws(token) + .getBody(); + TokenUserDTO userDTO = new TokenUserDTO(); + userDTO.setId(NumberUtils.toLong(claims.getId())); + userDTO.setAvatar(claims.get("avatar",String.class)); + userDTO.setUsername(claims.get("username",String.class)); + userDTO.setEmail(claims.get("email",String.class)); + userDTO.setRoles((List) claims.get("roles")); + return userDTO; + } + +} diff --git a/Spring-Security-Demo/src/main/resources/application.properties b/Spring-Security-Demo/src/main/resources/application.properties new file mode 100644 index 0000000..07419b0 --- /dev/null +++ b/Spring-Security-Demo/src/main/resources/application.properties @@ -0,0 +1,8 @@ +server.port=8080 + +logging.level.root=info +logging.level.org.springframework.security=debug + + +# jwt token签名密钥 +jwt.token.secret=quding2017 \ No newline at end of file