├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── cn
│ │ └── xujiajun
│ │ └── tastjava
│ │ ├── controller
│ │ └── HelloController.java
│ │ ├── core
│ │ ├── aop
│ │ │ ├── AbstractHandler.java
│ │ │ ├── AfterHandler.java
│ │ │ ├── BeforeHandler.java
│ │ │ └── ProxyFactory.java
│ │ └── ioc
│ │ │ ├── BeanFactory.java
│ │ │ └── ClassPathXmlApplicationContext.java
│ │ ├── dao
│ │ ├── UserDAO.java
│ │ └── impl
│ │ │ └── UserDAOImpl.java
│ │ ├── entity
│ │ └── User.java
│ │ ├── help
│ │ ├── DbHelper.java
│ │ └── MyBatisHelper.java
│ │ ├── mapper
│ │ └── UserMapper.java
│ │ ├── provider
│ │ ├── BaseProvider.java
│ │ ├── IProvider.java
│ │ ├── datasource
│ │ │ ├── BaseDataSourceProvider.java
│ │ │ ├── DruidProvider.java
│ │ │ ├── HikariCPProvider.java
│ │ │ └── IDataSourceProvider.java
│ │ └── jwt
│ │ │ └── JWTProvider.java
│ │ ├── rest
│ │ ├── HelloResource.java
│ │ ├── IndexResource.java
│ │ ├── UserResource.java
│ │ ├── exception
│ │ │ └── NotAuthorizedException.java
│ │ └── filter
│ │ │ ├── CORSOriginResponseFilter.java
│ │ │ ├── PoweredByResponseFilter.java
│ │ │ └── ResourceAuthFilter.java
│ │ ├── service
│ │ └── UserService.java
│ │ └── util
│ │ ├── PropsUtil.java
│ │ └── StrUtil.java
├── resources
│ ├── beans.xml
│ ├── config.properties
│ ├── jwt.properties
│ ├── mybatis
│ │ ├── Configuration.xml
│ │ └── mapper
│ │ │ └── UserMapper.xml
│ └── tinylog.properties
└── webapp
│ ├── WEB-INF
│ └── web.xml
│ └── index.jsp
└── test
└── java
└── cn
└── xujiajun
└── tastjava
└── rest
└── HelloResourceTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | tastjava.iml
3 | target/
4 | log.txt
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk:
3 | - oraclejdk8
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 徐佳军
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TastJava
2 | The RESTful Web API framework for Java
3 |
4 | ## Performance Test
5 |
6 | ### Test environment
7 |
8 | ```
9 | Server version: Apache Tomcat/9.0.0.M26
10 | Server number: 9.0.0.0
11 | OS Name: Mac OS X
12 | OS Version: 10.12.6
13 | Architecture: x86_64
14 | CPU:Intel Core i7 1.7 GHz *2
15 | RAM:8 GB
16 | JVM Version: 1.8.0_144-b01
17 | Mysql Version: 5.7.18
18 | ```
19 |
20 | Test Result (for reference only):
21 | ```
22 | ➜ tastjava git:(develop) ✗ ab -n 5000 -c 20 http://localhost:8080/tastjava/user/1
23 | This is ApacheBench, Version 2.3 <$Revision: 1757674 $>
24 | Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
25 | Licensed to The Apache Software Foundation, http://www.apache.org/
26 |
27 | Benchmarking localhost (be patient)
28 | Completed 500 requests
29 | Completed 1000 requests
30 | Completed 1500 requests
31 | Completed 2000 requests
32 | Completed 2500 requests
33 | Completed 3000 requests
34 | Completed 3500 requests
35 | Completed 4000 requests
36 | Completed 4500 requests
37 | Completed 5000 requests
38 | Finished 5000 requests
39 |
40 |
41 | Server Software:
42 | Server Hostname: localhost
43 | Server Port: 8080
44 |
45 | Document Path: /tastjava/user/1
46 | Document Length: 0 bytes
47 |
48 | Concurrency Level: 20
49 | Time taken for tests: 1.504 seconds
50 | Complete requests: 5000
51 | Failed requests: 0
52 | Total transferred: 365000 bytes
53 | HTML transferred: 0 bytes
54 | Requests per second: 3323.71 [#/sec] (mean)
55 | Time per request: 6.017 [ms] (mean)
56 | Time per request: 0.301 [ms] (mean, across all concurrent requests)
57 | Transfer rate: 236.94 [Kbytes/sec] received
58 |
59 | Connection Times (ms)
60 | min mean[+/-sd] median max
61 | Connect: 0 0 1.4 0 57
62 | Processing: 1 6 5.0 5 67
63 | Waiting: 1 5 4.9 5 65
64 | Total: 1 6 5.2 5 68
65 |
66 | Percentage of the requests served within a certain time (ms)
67 | 50% 5
68 | 66% 7
69 | 75% 8
70 | 80% 8
71 | 90% 10
72 | 95% 11
73 | 98% 14
74 | 99% 25
75 | 100% 68 (longest request)
76 | ```
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | cn.xujiajun.tastjava
5 | tastjava
6 | war
7 | 1.0.0
8 |
9 |
10 | UTF-8
11 | 1.8
12 | 4.12
13 | 5.0.0
14 | ${junit.version}.0
15 | 1.0.0
16 | 2.7.1
17 | 2.25.1
18 | 3.1.0
19 | 2.3.1
20 | 1.1
21 | 1.2
22 | 1.2
23 | 6.0.6
24 | 1.2.38
25 | 2.2
26 | 1.1.3
27 | 3.4.5
28 | 3.2.0
29 |
30 |
31 | tastjava Maven Webapp
32 | http://maven.apache.org
33 |
34 |
35 | org.junit.jupiter
36 | junit-jupiter-api
37 | ${junit.jupiter.version}
38 | test
39 |
40 |
41 | junit
42 | junit
43 | ${junit.version}
44 | test
45 |
46 |
47 |
48 | org.junit.platform
49 | junit-platform-launcher
50 | ${junit.platform.version}
51 | test
52 |
53 |
54 |
55 | org.junit.jupiter
56 | junit-jupiter-engine
57 | ${junit.jupiter.version}
58 |
59 |
60 |
61 | org.junit.vintage
62 | junit-vintage-engine
63 | ${junit.vintage.version}
64 |
65 |
66 |
67 |
68 | javax.servlet
69 | javax.servlet-api
70 | ${version.servlet.api}
71 | provided
72 |
73 |
74 |
75 |
76 | javax.servlet.jsp
77 | javax.servlet.jsp-api
78 | ${version.servlet.jsp.api}
79 | provided
80 |
81 |
82 |
83 |
84 | javax.servlet
85 | jstl
86 | ${version.jstl}
87 |
88 |
89 |
90 |
91 | jdom
92 | jdom
93 | ${version.jdom}
94 |
95 |
96 |
97 |
98 | org.tinylog
99 | tinylog
100 | ${version.tinylog}
101 |
102 |
103 |
104 |
105 | mysql
106 | mysql-connector-java
107 | ${version.mysql.connector}
108 |
109 |
110 |
111 | org.mybatis
112 | mybatis
113 | ${mybatis.version}
114 |
115 |
116 |
117 |
118 | com.alibaba
119 | fastjson
120 | ${version.fastjson}
121 |
122 |
123 |
124 |
125 |
126 | org.glassfish.jersey.containers
127 | jersey-container-servlet
128 | ${version.jersey}
129 |
130 |
131 |
132 |
133 | org.glassfish.jersey.core
134 | jersey-client
135 | ${version.jersey}
136 |
137 |
138 |
139 |
140 | org.glassfish.jersey.media
141 | jersey-media-json-jackson
142 | ${version.jersey}
143 |
144 |
145 |
146 |
147 | org.glassfish.jersey.media
148 | jersey-media-json-processing
149 | ${version.jersey}
150 |
151 |
152 |
153 | com.zaxxer
154 | HikariCP
155 | ${HikariCP.version}
156 |
157 |
158 |
159 | com.alibaba
160 | druid
161 | ${alibaba.druid.version}
162 |
163 |
164 |
165 | com.auth0
166 | java-jwt
167 | ${com.auth0.jwt.version}
168 |
169 |
170 |
171 |
172 | tastjava
173 |
174 |
175 | org.apache.maven.plugins
176 | maven-compiler-plugin
177 |
178 | ${version.jdk}
179 | ${version.jdk}
180 |
181 |
182 |
183 | maven-surefire-plugin
184 | 2.19.1
185 |
186 |
187 | **/Test*.java
188 | **/*Test.java
189 | **/*Tests.java
190 | **/*TestCase.java
191 |
192 |
193 |
194 | slow
195 |
200 |
201 |
202 |
203 |
204 | org.junit.platform
205 | junit-platform-surefire-provider
206 | ${junit.platform.version}
207 |
208 |
209 |
210 |
211 | org.apache.tomcat.maven
212 | tomcat7-maven-plugin
213 | ${version.tomcat.maven.plugin}
214 |
215 | http://localhost:8080/manager/text
216 | tomcat
217 | admin1
218 | admin1
219 | /${project.artifactId}
220 | true
221 |
222 |
223 |
224 |
225 |
226 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/controller/HelloController.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.controller;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import cn.xujiajun.tastjava.core.ioc.BeanFactory;
5 | import cn.xujiajun.tastjava.core.ioc.ClassPathXmlApplicationContext;
6 | import cn.xujiajun.tastjava.entity.User;
7 | import cn.xujiajun.tastjava.service.UserService;
8 | import org.pmw.tinylog.Logger;
9 |
10 | import javax.servlet.ServletException;
11 | import javax.servlet.annotation.WebServlet;
12 | import javax.servlet.http.HttpServlet;
13 | import javax.servlet.http.HttpServletRequest;
14 | import javax.servlet.http.HttpServletResponse;
15 | import java.io.IOException;
16 | import java.io.PrintWriter;
17 | import java.util.List;
18 |
19 | @WebServlet("/hello")
20 | public class HelloController extends HttpServlet {
21 | private String message;
22 |
23 | @Override
24 | public void init() throws ServletException {
25 | message = "hi,tastjava!";
26 | System.out.println("servlet初始化……");
27 | super.init();
28 | }
29 |
30 | @Override
31 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
32 |
33 | resp.setContentType("text/html");
34 | PrintWriter out = resp.getWriter();
35 |
36 | Logger.info("HelloController");
37 | try {
38 | BeanFactory factory = new ClassPathXmlApplicationContext();
39 | UserService userService = (UserService) factory.getBean("userService");
40 | List users = userService.GetUsers();
41 | String usersJson = JSON.toJSONString(users);
42 | out.println(usersJson);
43 | } catch (Exception e) {
44 | // Handle it.
45 | out.println("Exception
");
46 | out.println("" + e.getMessage() + "
");
47 |
48 | e.printStackTrace();
49 | out.println("------------------------------");
50 | for (StackTraceElement elem : e.getStackTrace()) {
51 | out.println("
");
52 | out.println(elem);
53 | }
54 | }
55 |
56 | out.println("" + message + "
");
57 | }
58 |
59 | @Override
60 | public void destroy() {
61 | System.out.println("servlet销毁!");
62 | super.destroy();
63 | }
64 | }
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/core/aop/AbstractHandler.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.core.aop;
2 |
3 | import java.lang.reflect.InvocationHandler;
4 |
5 | public abstract class AbstractHandler implements InvocationHandler {
6 |
7 | /** The target object. */
8 | private Object targetObject;
9 |
10 | /**
11 | * Sets the target object.
12 | *
13 | * @param targetObject the new target object
14 | */
15 | public void setTargetObject(Object targetObject) {
16 | this.targetObject = targetObject;
17 | }
18 |
19 | /**
20 | * Gets the target object.
21 | *
22 | * @return the target object
23 | */
24 | public Object getTargetObject() {
25 | return targetObject;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/core/aop/AfterHandler.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.core.aop;
2 |
3 | import java.lang.reflect.Method;
4 |
5 | public abstract class AfterHandler extends AbstractHandler {
6 |
7 | /**
8 | * Handles after the execution of method.
9 | *
10 | * @param proxy the proxy
11 | * @param method the method
12 | * @param args the args
13 | */
14 | public abstract void handleAfter(Object proxy, Method method, Object[] args);
15 |
16 | /* (non-Javadoc)
17 | * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
18 | */
19 | @Override
20 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
21 |
22 | Object result = method.invoke(getTargetObject(), args);
23 | handleAfter(proxy, method, args);
24 | return result;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/core/aop/BeforeHandler.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.core.aop;
2 |
3 | import java.lang.reflect.Method;
4 |
5 | public abstract class BeforeHandler extends AbstractHandler {
6 |
7 | /**
8 | * Handles before execution of actual method.
9 | *
10 | * @param proxy the proxy
11 | * @param method the method
12 | * @param args the args
13 | */
14 | public abstract void handleBefore(Object proxy, Method method, Object[] args);
15 |
16 | /* (non-Javadoc)
17 | * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
18 | */
19 | @Override
20 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
21 | handleBefore(proxy, method, args);
22 | return method.invoke(getTargetObject(), args);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/core/aop/ProxyFactory.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.core.aop;
2 |
3 | import java.lang.reflect.Proxy;
4 | import java.util.List;
5 |
6 | public class ProxyFactory {
7 |
8 | /**
9 | * Gets the proxy.
10 | *
11 | * @param targetObject the target object
12 | * @param handlers the handlers
13 | * @return the proxy
14 | */
15 | public static Object getProxy(Object targetObject,
16 | List handlers) {
17 | Object proxyObject = null;
18 | if (handlers.size() > 0) {
19 | proxyObject = targetObject;
20 | for (int i = 0; i < handlers.size(); i++) {
21 | handlers.get(i).setTargetObject(proxyObject);
22 | proxyObject = Proxy.newProxyInstance(targetObject.getClass()
23 | .getClassLoader(), targetObject.getClass()
24 | .getInterfaces(), handlers.get(i));
25 | }
26 | return proxyObject;
27 | } else {
28 | return targetObject;
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/core/ioc/BeanFactory.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.core.ioc;
2 |
3 | public interface BeanFactory {
4 | Object getBean(String name);
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/core/ioc/ClassPathXmlApplicationContext.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.core.ioc;
2 |
3 | import org.jdom.Document;
4 | import org.jdom.Element;
5 | import org.jdom.input.SAXBuilder;
6 |
7 | import java.io.File;
8 | import java.lang.reflect.Method;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | public class ClassPathXmlApplicationContext implements BeanFactory {
14 | private Map beans = new HashMap();
15 |
16 | public ClassPathXmlApplicationContext() throws Exception {
17 | SAXBuilder builder = new SAXBuilder();
18 |
19 | String basedir = this.getClass().getClassLoader().getResource("/").getPath();
20 |
21 | File xmlFile = new File(basedir + "beans.xml");
22 | // 构造文档对象
23 | Document document = builder.build(xmlFile);
24 | // 获取根元素
25 | Element root = document.getRootElement();
26 | // 取到根元素所有元素
27 | List list = root.getChildren();
28 |
29 | setBeans(list);
30 | }
31 |
32 | /**
33 | * set Beans
34 | *
35 | * @param list
36 | * @throws Exception
37 | */
38 | private void setBeans(List list) throws Exception {
39 | for (int i = 0; i < list.size(); i++) {
40 | Element element = (Element) list.get(i);
41 |
42 | String id = element.getAttributeValue("id");
43 |
44 | String className = element.getAttributeValue("class");
45 |
46 | Object o = Class.forName(className).newInstance();
47 |
48 | beans.put(id, o);
49 |
50 | setProperty(element, o);
51 | }
52 | }
53 |
54 | /**
55 | * setProperty inject
56 | *
57 | * @param element
58 | * @param o
59 | * @throws Exception
60 | */
61 | private void setProperty(Element element, Object o) throws Exception {
62 | for (Element property : (List) element.getChildren("property")) {
63 | String name = property.getAttributeValue("name");
64 | String bean = property.getAttributeValue("bean");
65 | //从beans.xml中根据id取到类的对象
66 | Object beanObj = this.getBean(bean);
67 | // System.out.println(beanObj);//com.tastjava.dao.impl.UserDAOImpl@eed1f14
68 | String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
69 | // 反射机制对方法进行调用,将对象在加载bean时就注入到环境上下文中
70 | Method m = o.getClass().getMethod(methodName, beanObj.getClass().getInterfaces()[0]);
71 | m.invoke(o, beanObj);
72 | }
73 | }
74 |
75 | @Override
76 | public Object getBean(String name) {
77 | return beans.get(name);
78 | }
79 | }
80 |
81 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/dao/UserDAO.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.dao;
2 |
3 | import cn.xujiajun.tastjava.entity.User;
4 |
5 | import java.util.List;
6 |
7 | public interface UserDAO {
8 | List GetUsers();
9 | User GetUser();
10 | User GetUser2(int id);
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/dao/impl/UserDAOImpl.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.dao.impl;
2 |
3 | import cn.xujiajun.tastjava.dao.UserDAO;
4 | import cn.xujiajun.tastjava.help.DbHelper;
5 | import cn.xujiajun.tastjava.entity.User;
6 | import cn.xujiajun.tastjava.help.MyBatisHelper;
7 | import cn.xujiajun.tastjava.mapper.UserMapper;
8 | import org.apache.ibatis.session.SqlSession;
9 | import org.apache.ibatis.session.SqlSessionFactory;
10 | import org.pmw.tinylog.Logger;
11 |
12 | import java.io.IOException;
13 | import java.sql.*;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | public class UserDAOImpl implements UserDAO {
18 | @Override
19 | public List GetUsers() {
20 | // try {
21 | // List listUser = new ArrayList();
22 | //
23 | // Connection jdbcConnection = DbHelper.getConnect();
24 | // String sql = "SELECT * FROM user ";
25 | // Statement statement = jdbcConnection.createStatement();
26 | // ResultSet resultSet = statement.executeQuery(sql);
27 | //
28 | // while (resultSet.next()) {
29 | // int id = resultSet.getInt("id");
30 | // String userName = resultSet.getString("userName");
31 | // String password = resultSet.getString("password");
32 | //
33 | // User user = new User();
34 | // user.setId(id);
35 | // user.setPassword(password);
36 | // user.setUserName(userName);
37 | // listUser.add(user);
38 | // }
39 | //
40 | // resultSet.close();
41 | // statement.close();
42 | // DbHelper.disconnect();
43 | // Logger.info(listUser);
44 | // return listUser;
45 | //
46 | // } catch (SQLException e) {
47 | // throw new RuntimeException("Exception in GetUsers,msg: " + e.getMessage() + e.toString(), e);
48 | // }
49 | return null;
50 | }
51 |
52 | public User GetUser() {
53 | SqlSessionFactory mySqlSessionFactory = MyBatisHelper.getSqlSessionFactory();
54 | SqlSession session = mySqlSessionFactory.openSession();
55 |
56 | try {
57 | UserMapper userMapper = session.getMapper(UserMapper.class);
58 | User user = userMapper.getUser(1);
59 | return user;
60 | } finally {
61 | session.close();
62 | }
63 | }
64 |
65 | public User GetUser2(int id) {
66 | Connection jdbcConnection = null;
67 | try {
68 | // jdbcConnection = DbHelper.getDatasource().getConnection();
69 | // jdbcConnection = DbHelper.getDruidDataSource().getConnection();
70 | jdbcConnection = DbHelper.getDatasource().getConnection();
71 | String sql = "SELECT * FROM user Where id =?";
72 | PreparedStatement statement = jdbcConnection.prepareStatement(sql);
73 | statement.setInt(1, id);
74 | ResultSet resultSet = statement.executeQuery();
75 |
76 | if (resultSet.next()) {
77 | int userid = resultSet.getInt("id");
78 | String userName = resultSet.getString("userName");
79 | String password = resultSet.getString("password");
80 |
81 | User user = new User();
82 | user.setId(userid);
83 | user.setPassword(password);
84 | user.setUserName(userName);
85 | return user;
86 | }
87 |
88 | resultSet.close();
89 | statement.close();
90 |
91 |
92 | } catch (SQLException e) {
93 | throw new RuntimeException("Exception in GetUser2,msg: " + e.getMessage() + e.toString(), e);
94 | } finally {
95 | if (jdbcConnection != null) try {
96 | jdbcConnection.close();
97 | } catch (Exception ignore) {
98 | }
99 | }
100 | return null;
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/entity/User.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.entity;
2 |
3 | public class User {
4 | private int id;
5 | private String userName;
6 | private String password;
7 |
8 | /**
9 | * @return userId
10 | */
11 | public int getId() {
12 | return id;
13 | }
14 |
15 | /**
16 | * @param id the userId to set
17 | */
18 | public void setId(int id) {
19 | this.id = id;
20 | }
21 |
22 | /**
23 | * @return the userName
24 | */
25 | public String getUserName() {
26 | return userName;
27 | }
28 |
29 | /**
30 | * @param userName the userName to set
31 | */
32 | public void setUserName(String userName) {
33 | this.userName = userName;
34 | }
35 |
36 | /**
37 | * @return the password
38 | */
39 | public String getPassword() {
40 | return password;
41 | }
42 |
43 | /**
44 | * @param password the password to set
45 | */
46 | public void setPassword(String password) {
47 | this.password = password;
48 | }
49 |
50 | // public String toString() {
51 | // StringBuffer sb = new StringBuffer();
52 | // sb.append(this.id);
53 | // sb.append(this.userName);
54 | // sb.append(this.password);
55 | // return sb.toString();
56 | // }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/help/DbHelper.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.help;
2 |
3 | import cn.xujiajun.tastjava.provider.datasource.DruidProvider;
4 | import cn.xujiajun.tastjava.provider.datasource.HikariCPProvider;
5 | import cn.xujiajun.tastjava.util.PropsUtil;
6 | import cn.xujiajun.tastjava.util.StrUtil;
7 |
8 | import javax.sql.DataSource;
9 | import java.util.Properties;
10 |
11 | public class DbHelper {
12 | private static String jdbcProvider;
13 |
14 | static {
15 | Properties conf = PropsUtil.loadProps("config.properties");
16 | jdbcProvider = conf.getProperty("jdbc.provider");
17 | }
18 |
19 | public static DataSource getDatasource() {
20 | if (StrUtil.isBlank(jdbcProvider) || (!StrUtil.isBlank(jdbcProvider) && ("HikariCP" == jdbcProvider))) {
21 | HikariCPProvider dataSourceProvider = HikariCPProvider.getInstance();
22 | dataSourceProvider.register();
23 | return dataSourceProvider.getDataSource();
24 | }
25 |
26 | if (!StrUtil.isBlank(jdbcProvider) && ("Druid" == jdbcProvider)) {
27 | DruidProvider dataSourceProvider = DruidProvider.getInstance();
28 | dataSourceProvider.register();
29 | return dataSourceProvider.getDataSource();
30 | }
31 |
32 | return null;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/help/MyBatisHelper.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.help;
2 |
3 | import org.apache.ibatis.io.Resources;
4 | import org.apache.ibatis.session.SqlSessionFactory;
5 | import org.apache.ibatis.session.SqlSessionFactoryBuilder;
6 |
7 | import java.io.IOException;
8 | import java.io.Reader;
9 |
10 | public class MyBatisHelper {
11 | private static String resource = "mybatis/Configuration.xml";
12 |
13 | private static class sqlSessionFactoryBuilderHolder {
14 | private static final SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
15 | }
16 |
17 | public static SqlSessionFactory getSqlSessionFactory() {
18 |
19 | try {
20 | Reader reader = getReader();
21 | SqlSessionFactory sessionFactory = sqlSessionFactoryBuilderHolder.sqlSessionFactoryBuilder.build(reader);
22 | return sessionFactory;
23 | } catch (IOException e) {
24 | throw new RuntimeException("Exception in getSqlSessionFactory", e);
25 | }
26 |
27 | }
28 |
29 | private static Reader getReader() throws IOException {
30 | Reader reader = Resources.getResourceAsReader(resource);
31 | return reader;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/mapper/UserMapper.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.mapper;
2 |
3 | import cn.xujiajun.tastjava.entity.User;
4 |
5 | public interface UserMapper {
6 | User getUser(int id);
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/provider/BaseProvider.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.provider;
2 |
3 | public class BaseProvider {
4 | protected static boolean IsRegistered = false;
5 | protected final static boolean HAS_REGISTERED = true;
6 | protected final static boolean NOT_REGISTERED = false;
7 |
8 | public void setIsRegistered(boolean isRegistered) {
9 | IsRegistered = isRegistered;
10 | }
11 |
12 | public boolean getIsRegistered() {
13 | return IsRegistered;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/provider/IProvider.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.provider;
2 |
3 | public interface IProvider {
4 | boolean register();
5 | }
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/provider/datasource/BaseDataSourceProvider.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.provider.datasource;
2 |
3 | import cn.xujiajun.tastjava.provider.BaseProvider;
4 | import cn.xujiajun.tastjava.util.PropsUtil;
5 |
6 | import java.util.Properties;
7 |
8 | public class BaseDataSourceProvider extends BaseProvider {
9 | protected static String jdbcURL;
10 | protected static String jdbcDriver;
11 | protected static String jdbcUsername;
12 | protected static String jdbcPassword;
13 |
14 | static {
15 | Properties conf = PropsUtil.loadProps("config.properties");
16 | jdbcURL = conf.getProperty("jdbc.url");
17 | jdbcUsername = conf.getProperty("jdbc.username");
18 | jdbcPassword = conf.getProperty("jdbc.password");
19 | jdbcDriver = conf.getProperty("jdbc.driver");
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/provider/datasource/DruidProvider.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.provider.datasource;
2 |
3 | import cn.xujiajun.tastjava.provider.IProvider;
4 | import cn.xujiajun.tastjava.util.StrUtil;
5 | import com.alibaba.druid.pool.DruidDataSource;
6 |
7 | import javax.sql.DataSource;
8 |
9 | public class DruidProvider extends BaseDataSourceProvider implements IProvider, IDataSourceProvider {
10 |
11 | private static DruidDataSource ds;
12 | private String name = null;
13 |
14 | /**
15 | * 最大连接池数量
16 | */
17 | private int maxActive = 100;
18 |
19 | /**
20 | * 最小连接池数量
21 | */
22 | private int minIdle = 10;
23 |
24 | /**
25 | * 用来检测连接是否有效的sql
26 | */
27 | private String validationQuery = "select 1";
28 |
29 | /**
30 | * 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
31 | */
32 | private boolean testOnBorrow = false;
33 |
34 | /**
35 | * 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
36 | */
37 | private boolean testOnReturn = false;
38 |
39 | /**
40 | * 建议配置为true,不影响性能,并且保证安全性。
41 | * 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
42 | */
43 | private boolean testWhileIdle = true;
44 |
45 | /**
46 | * 有两个含义:
47 | * 1) Destroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableIdleTimeMillis则关闭物理连接。
48 | * 2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明
49 | * 单位是毫秒
50 | */
51 | private long timeBetweenEvictionRunsMillis = 60000;
52 |
53 | /**
54 | * 连接保持空闲而不被驱逐的最小时间
55 | * 单位是毫秒
56 | */
57 | private long minEvictableIdleTimeMillis = 300000;
58 |
59 |
60 | private DruidProvider() {
61 | }
62 |
63 | private static class SingletonHolder {
64 | private static final DruidProvider INSTANCE = new DruidProvider();
65 | }
66 |
67 | public static final DruidProvider getInstance() {
68 | return SingletonHolder.INSTANCE;
69 | }
70 |
71 | public void setName(String name) {
72 | this.name = name;
73 | }
74 |
75 | public void setMaxActive(int maxActive) {
76 | this.maxActive = maxActive;
77 | }
78 |
79 | public void setMinIdle(int minIdle) {
80 | this.minIdle = minIdle;
81 | }
82 |
83 | public void setValidationQuery(String validationQuery) {
84 | this.validationQuery = validationQuery;
85 | }
86 |
87 | public void setTestOnBorrow(boolean testOnBorrow) {
88 | this.testOnBorrow = testOnBorrow;
89 | }
90 |
91 | public void setTestOnReturn(boolean testOnReturn) {
92 | this.testOnReturn = testOnReturn;
93 | }
94 |
95 | public void setTestWhileIdle(boolean testWhileIdle) {
96 | this.testWhileIdle = testWhileIdle;
97 | }
98 |
99 | public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
100 | this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
101 | }
102 |
103 | public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
104 | this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
105 | }
106 |
107 | @Override
108 | public boolean register() {
109 | if (IsRegistered) {
110 | return HAS_REGISTERED;
111 | }
112 |
113 | DruidDataSource ds = new DruidDataSource();
114 |
115 | if (!StrUtil.isBlank(name)) {
116 | ds.setName(this.name);
117 | }
118 |
119 | ds.setUrl(jdbcURL);
120 | ds.setDriverClassName(jdbcDriver);
121 | ds.setUsername(jdbcUsername);
122 | ds.setPassword(jdbcPassword);
123 |
124 | ds.setMinIdle(minIdle);
125 | ds.setMaxActive(maxActive);
126 | ds.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
127 | ds.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
128 | ds.setValidationQuery(validationQuery);
129 |
130 | ds.setTestWhileIdle(testWhileIdle);
131 | ds.setTestOnBorrow(testOnBorrow);
132 | ds.setTestOnReturn(testOnReturn);
133 |
134 | setDataSource(ds);
135 | setIsRegistered(HAS_REGISTERED);
136 | return HAS_REGISTERED;
137 | }
138 |
139 | @Override
140 | public DataSource getDataSource() {
141 | return ds;
142 | }
143 |
144 | private void setDataSource(DruidDataSource datasource) {
145 | ds = datasource;
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/provider/datasource/HikariCPProvider.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.provider.datasource;
2 |
3 | import cn.xujiajun.tastjava.provider.IProvider;
4 | import cn.xujiajun.tastjava.util.StrUtil;
5 | import com.zaxxer.hikari.HikariDataSource;
6 |
7 | import javax.sql.DataSource;
8 |
9 | public class HikariCPProvider extends BaseDataSourceProvider implements IProvider, IDataSourceProvider {
10 |
11 | private static HikariDataSource ds;
12 |
13 | /**
14 | * This property controls the default auto-commit behavior of connections returned from the pool.
15 | * It is a boolean value.Default: true
16 | */
17 | private boolean autoCommit = true;
18 |
19 | /**
20 | * This property controls the maximum number of milliseconds that a client (that's you) will wait for a connection from the pool.
21 | * If this time is exceeded without a connection becoming available, a SQLException will be thrown.
22 | * Lowest acceptable connection timeout is 250 ms. Default: 30000 (30 seconds)
23 | */
24 | private long connectionTimeout = 30000;
25 |
26 | /**
27 | * This property controls the maximum amount of time that a connection is allowed to sit idle in the pool.
28 | * The minimum allowed value is 10000ms (10 seconds). Default: 600000 (10 minutes)
29 | */
30 | private long idleTimeout = 600000;
31 |
32 | /**
33 | * This property controls the maximum lifetime of a connection in the pool
34 | * Default: 1800000 (30 minutes)
35 | */
36 | private long maxLifetime = 1800000;
37 |
38 |
39 | /**
40 | * This property controls the maximum size that the pool is allowed to reach, including both idle and in-use connections
41 | * about pool sizing: https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
42 | * Default: 10
43 | */
44 | private int maximumPoolSize = 10;
45 |
46 | /**
47 | * This property represents a user-defined name for the connection pool and appears mainly in logging
48 | * and JMX management consoles to identify pools and pool configurations.
49 | * Default: auto-generated
50 | */
51 | private String poolName = null;
52 |
53 | /**
54 | * This property sets the default catalog for databases that support the concept of catalogs.
55 | * If this property is not specified, the default catalog defined by the JDBC driver is used.
56 | * Default: driver default
57 | */
58 | private String catalog = null;
59 |
60 | /**
61 | * This property sets a SQL statement that will be executed after every new connection creation before adding it to the pool.
62 | * If this SQL is not valid or throws an exception, it will be treated as a connection failure and the standard retry logic will be followed.
63 | * Default: none
64 | */
65 | private String connectionInitSql = null;
66 |
67 | /**
68 | * This property controls the default transaction isolation level of connections returned from the pool
69 | * Default: driver default
70 | */
71 | private String transactionIsolation = null;
72 |
73 | /**
74 | * This property controls the maximum amount of time that a connection will be tested for aliveness.
75 | * This value must be less than the connectionTimeout. Lowest acceptable validation timeout is 250 ms.
76 | * Default: 5000
77 | */
78 | private long validationTimeout = 5000;
79 |
80 | /**
81 | * This property controls the amount of time that a connection can be out of the pool before a message is logged indicating a possible connection leak.
82 | * A value of 0 means leak detection is disabled.Lowest acceptable value for enabling leak detection is 2000 (2 seconds).
83 | * Default: 0
84 | */
85 | private long leakDetectionThreshold = 0;
86 |
87 | private static class SingletonHolder {
88 | private static final HikariCPProvider INSTANCE = new HikariCPProvider();
89 | }
90 |
91 | private HikariCPProvider() {
92 | }
93 |
94 | public static final HikariCPProvider getInstance() {
95 | return SingletonHolder.INSTANCE;
96 | }
97 |
98 | public void setAutoCommit(boolean autoCommit) {
99 | this.autoCommit = autoCommit;
100 | }
101 |
102 | public void setConnectionTimeout(long connectionTimeout) {
103 | this.connectionTimeout = connectionTimeout;
104 | }
105 |
106 | public void setIdleTimeout(long idleTimeout) {
107 | this.idleTimeout = idleTimeout;
108 | }
109 |
110 | public void setMaxLifetime(long maxLifetime) {
111 | this.maxLifetime = maxLifetime;
112 | }
113 |
114 | public void setMaximumPoolSize(int maximumPoolSize) {
115 | this.maximumPoolSize = maximumPoolSize;
116 | }
117 |
118 | public void setPoolName(String poolName) {
119 | this.poolName = poolName;
120 | }
121 |
122 | public void setCatalog(String catalog) {
123 | this.catalog = catalog;
124 | }
125 |
126 | public void setConnectionInitSql(String connectionInitSql) {
127 | this.connectionInitSql = connectionInitSql;
128 | }
129 |
130 | public void setTransactionIsolation(String transactionIsolation) {
131 | this.transactionIsolation = transactionIsolation;
132 | }
133 |
134 | public void setValidationTimeout(long validationTimeout) {
135 | this.validationTimeout = validationTimeout;
136 | }
137 |
138 | public void setLeakDetectionThreshold(long leakDetectionThreshold) {
139 | this.leakDetectionThreshold = leakDetectionThreshold;
140 | }
141 |
142 | @Override
143 | public boolean register() {
144 | if (IsRegistered) {
145 | return HAS_REGISTERED;
146 | }
147 |
148 | HikariDataSource ds = new HikariDataSource();
149 |
150 | //basic config
151 | ds.setJdbcUrl(jdbcURL);
152 | ds.setDriverClassName(jdbcDriver);
153 | ds.setUsername(jdbcUsername);
154 | ds.setPassword(jdbcPassword);
155 |
156 | //custom config
157 | ds.setAutoCommit(autoCommit);
158 | ds.setConnectionTimeout(connectionTimeout);
159 | ds.setIdleTimeout(idleTimeout);
160 | ds.setMaxLifetime(maxLifetime);
161 | ds.setMaximumPoolSize(maximumPoolSize);
162 | ds.setValidationTimeout(validationTimeout);
163 | ds.setLeakDetectionThreshold(leakDetectionThreshold);
164 |
165 | if (!StrUtil.isBlank(poolName)) {
166 | ds.setPoolName(poolName);
167 | }
168 |
169 | if (!StrUtil.isBlank(catalog)) {
170 | ds.setCatalog(catalog);
171 | }
172 |
173 | if (!StrUtil.isBlank(connectionInitSql)) {
174 | ds.setConnectionInitSql(connectionInitSql);
175 | }
176 |
177 | if (!StrUtil.isBlank(transactionIsolation)) {
178 | ds.setTransactionIsolation(transactionIsolation);
179 | }
180 |
181 | if (jdbcURL.contains(":mysql:")) {
182 | ds.addDataSourceProperty("cachePrepStmts", "true");
183 | ds.addDataSourceProperty("prepStmtCacheSize", "250");
184 | ds.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
185 | ds.addDataSourceProperty("useServerPrepStmts", "true");
186 | }
187 |
188 | setDataSource(ds);
189 | setIsRegistered(HAS_REGISTERED);
190 | return HAS_REGISTERED;
191 | }
192 |
193 | @Override
194 | public DataSource getDataSource() {
195 | return ds;
196 | }
197 |
198 | private void setDataSource(HikariDataSource datasource) {
199 | ds = datasource;
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/provider/datasource/IDataSourceProvider.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.provider.datasource;
2 |
3 | import javax.sql.DataSource;
4 |
5 | public interface IDataSourceProvider {
6 | DataSource getDataSource();
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/provider/jwt/JWTProvider.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.provider.jwt;
2 |
3 | import cn.xujiajun.tastjava.util.PropsUtil;
4 | import com.auth0.jwt.JWT;
5 | import com.auth0.jwt.JWTVerifier;
6 | import com.auth0.jwt.algorithms.Algorithm;
7 | import com.auth0.jwt.exceptions.JWTCreationException;
8 | import com.auth0.jwt.exceptions.JWTVerificationException;
9 | import com.auth0.jwt.interfaces.DecodedJWT;
10 |
11 | import java.io.UnsupportedEncodingException;
12 | import java.util.Properties;
13 |
14 | public class JWTProvider {
15 |
16 | private static String JWTSecret;
17 | private static String JWTIssuer = "tastjava";
18 |
19 | static {
20 | Properties conf = PropsUtil.loadProps("jwt.properties");
21 | JWTSecret = conf.getProperty("jwt.secret");
22 | }
23 | public static String createToken(int uid) {
24 | try {
25 | Algorithm algorithm = Algorithm.HMAC256(JWTSecret);
26 | String token = JWT.create()
27 | .withIssuer(JWTIssuer)
28 | .withClaim("uid", uid)
29 | .sign(algorithm);
30 | return token;
31 | } catch (UnsupportedEncodingException exception) {
32 | throw new RuntimeException("Exception in createToken,msg: " + exception.getMessage() + exception.toString(), exception);
33 | //UTF-8 encoding not supported
34 | } catch (JWTCreationException exception) {
35 | //Invalid Signing configuration / Couldn't convert Claims.
36 | throw new RuntimeException("Exception in createToken,msg: " + exception.getMessage() + exception.toString(), exception);
37 | }
38 | }
39 |
40 | public static DecodedJWT verifyToken(String token) {
41 | try {
42 | Algorithm algorithm = Algorithm.HMAC256(JWTSecret);
43 | JWTVerifier verifier = JWT.require(algorithm)
44 | .withIssuer(JWTIssuer)
45 | .build();
46 | DecodedJWT jwt = verifier.verify(token);
47 | return jwt;
48 | } catch (UnsupportedEncodingException exception) {
49 | throw new RuntimeException("Exception in verifyToken,msg: " + exception.getMessage() + exception.toString(), exception);
50 | //UTF-8 encoding not supported
51 | } catch (JWTVerificationException exception) {
52 | //Invalid signature/claims
53 | throw new RuntimeException("Exception in verifyToken,msg: " + exception.getMessage() + exception.toString(), exception);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/rest/HelloResource.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.rest;
2 |
3 | import org.pmw.tinylog.Logger;
4 |
5 | import javax.ws.rs.*;
6 | import javax.ws.rs.core.Context;
7 | import javax.ws.rs.core.MediaType;
8 | import javax.ws.rs.core.UriInfo;
9 | import java.io.Serializable;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | @Path("/hi")
14 | public class HelloResource {
15 | @GET
16 | @Produces(MediaType.TEXT_PLAIN)
17 | public String getMessage() {
18 | return "Hello world!";
19 | }
20 |
21 | @Path("/{name}")
22 | @GET
23 | @Produces(MediaType.TEXT_PLAIN)
24 | public String getName(@PathParam("name") String name) {
25 | return "Hello," + name;
26 | }
27 |
28 | @POST
29 | @Path("/add")
30 | @Produces(MediaType.TEXT_PLAIN)
31 | public String add(@FormParam("name") String name) {
32 | return "add name:" + name;
33 | }
34 |
35 | @DELETE
36 | @Path("/{id}")
37 | @Produces(MediaType.TEXT_PLAIN)
38 | public String remove(@FormParam("id") int id) {
39 | return "remove id:" + id;
40 | }
41 |
42 | @PUT
43 | @Path("/update")
44 | @Produces(MediaType.TEXT_PLAIN)
45 | public String update(@FormParam("name") String name) {
46 | return "update name:" + name;
47 | }
48 |
49 | @GET
50 | @Path("/json")
51 | @Produces(MediaType.APPLICATION_JSON)
52 | public List sayHiWithJson() {
53 | List ListMyCustomBean = new ArrayList();
54 | MyCustomBean beanOne = new MyCustomBean();
55 | beanOne.setAge(27);
56 | beanOne.setName("johnny");
57 | MyCustomBean beanTwo = new MyCustomBean();
58 | beanTwo.setAge(28);
59 | beanTwo.setName("jersey");
60 | ListMyCustomBean.add(beanOne);
61 | ListMyCustomBean.add(beanTwo);
62 | return ListMyCustomBean;
63 | }
64 |
65 | @GET
66 | @Path("/path/{id}")
67 | public String sayWithParam(@PathParam("id") int id) {
68 | return "get param id value:" + id;
69 | }
70 |
71 | @GET
72 | @Path("/context/{id}")
73 | public String sayTestContext(@Context UriInfo ui,@PathParam("id") int id) {
74 | Logger.info(ui.getPathParameters());
75 | return ui.getPath();
76 | }
77 | }
78 |
79 |
80 | class MyCustomBean implements Serializable {
81 |
82 | private String name;
83 | private int age;
84 |
85 | public String getName() {
86 | return name;
87 | }
88 |
89 | public void setName(String name) {
90 | this.name = name;
91 | }
92 |
93 | public int getAge() {
94 | return age;
95 | }
96 |
97 | public void setAge(int age) {
98 | this.age = age;
99 | }
100 | }
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/rest/IndexResource.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.rest;
2 |
3 | import javax.ws.rs.GET;
4 | import javax.ws.rs.Path;
5 | import javax.ws.rs.Produces;
6 | import javax.ws.rs.core.MediaType;
7 |
8 | @Path("/")
9 | public class IndexResource {
10 | @GET
11 | @Produces(MediaType.TEXT_PLAIN)
12 | public String getMessage() {
13 | return "hi,tastjava!";
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/rest/UserResource.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.rest;
2 |
3 | import cn.xujiajun.tastjava.core.ioc.BeanFactory;
4 | import cn.xujiajun.tastjava.core.ioc.ClassPathXmlApplicationContext;
5 | import cn.xujiajun.tastjava.entity.User;
6 | import cn.xujiajun.tastjava.provider.jwt.JWTProvider;
7 | import cn.xujiajun.tastjava.service.UserService;
8 | import org.pmw.tinylog.Logger;
9 |
10 | import javax.ws.rs.*;
11 | import javax.ws.rs.core.Cookie;
12 | import javax.ws.rs.core.MediaType;
13 | import javax.ws.rs.core.NewCookie;
14 | import javax.ws.rs.core.Response;
15 |
16 | @Path("/user")
17 | public class UserResource {
18 | @Path("/{id}")
19 | @GET
20 | @Produces(MediaType.APPLICATION_JSON)
21 | public User getUser(@PathParam("id") int id) {
22 | try {
23 | BeanFactory factory = new ClassPathXmlApplicationContext();
24 | UserService userService = (UserService) factory.getBean("userService");
25 | User user = userService.GetUser(id);
26 | return user;
27 |
28 | } catch (Exception e) {
29 | Logger.error(e.toString());
30 | // return "Exception:"+e.toString()+". msg:"+e.getMessage()+". trace:"+e.getStackTrace();
31 | }
32 | return null;
33 | }
34 |
35 | @Path("/login")
36 | @GET
37 | @Produces(MediaType.TEXT_PLAIN)
38 | public Response login() {
39 | String token = JWTProvider.createToken(1);
40 | NewCookie cookie = new NewCookie("jwt-authToken", token,"/", "", "comment", 3600, false);
41 | return Response.ok("OK").cookie(cookie).build();
42 | }
43 |
44 | @GET
45 | @Path("/logout")
46 | @Produces(MediaType.TEXT_PLAIN)
47 | public Response logout(@CookieParam("jwt-authToken") Cookie cookie) {
48 | if (cookie != null) {
49 | NewCookie newCookie = new NewCookie("jwt-authToken", "","/", "", "comment", 0, false);
50 | return Response.ok("OK").cookie(newCookie).build();
51 | }
52 | return Response.ok("OK - No session").build();
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/rest/exception/NotAuthorizedException.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.rest.exception;
2 |
3 | import javax.ws.rs.WebApplicationException;
4 | import javax.ws.rs.core.MediaType;
5 | import javax.ws.rs.core.Response;
6 |
7 | public class NotAuthorizedException extends WebApplicationException {
8 | public NotAuthorizedException(String message) {
9 | super(Response.status(Response.Status.UNAUTHORIZED)
10 | .entity(message).type(MediaType.TEXT_PLAIN).build());
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/rest/filter/CORSOriginResponseFilter.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.rest.filter;
2 |
3 | import javax.ws.rs.container.ContainerRequestContext;
4 | import javax.ws.rs.container.ContainerResponseContext;
5 | import javax.ws.rs.container.ContainerResponseFilter;
6 | import javax.ws.rs.ext.Provider;
7 | import java.io.IOException;
8 |
9 | @Provider
10 | public class CORSOriginResponseFilter implements ContainerResponseFilter {
11 | @Override
12 | public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
13 | containerRequestContext.getHeaders().add("Access-Control-Allow-Origin", "*");
14 | containerRequestContext.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
15 | containerRequestContext.getHeaders().add("Access-Control-Allow-Credentials", "true");
16 | containerRequestContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
17 | containerRequestContext.getHeaders().add("Access-Control-Max-Age", "1209600");
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/rest/filter/PoweredByResponseFilter.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.rest.filter;
2 |
3 | import javax.ws.rs.container.ContainerRequestContext;
4 | import javax.ws.rs.container.ContainerResponseContext;
5 | import javax.ws.rs.container.ContainerResponseFilter;
6 | import javax.ws.rs.ext.Provider;
7 | import java.io.IOException;
8 |
9 | @Provider
10 | public class PoweredByResponseFilter implements ContainerResponseFilter {
11 |
12 | @Override
13 | public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
14 | throws IOException {
15 |
16 | responseContext.getHeaders().add("X-Powered-By", "tastjava :-)");
17 | }
18 | }
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/rest/filter/ResourceAuthFilter.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.rest.filter;
2 |
3 | import cn.xujiajun.tastjava.provider.jwt.JWTProvider;
4 | import org.pmw.tinylog.Logger;
5 |
6 | import javax.ws.rs.container.ContainerRequestContext;
7 | import javax.ws.rs.container.ContainerRequestFilter;
8 | import javax.ws.rs.core.Cookie;
9 | import javax.ws.rs.core.Response;
10 | import javax.ws.rs.core.UriInfo;
11 | import javax.ws.rs.ext.Provider;
12 | import java.io.IOException;
13 | import java.net.URI;
14 | import java.util.Map;
15 |
16 | //import cn.xujiajun.tastjava.rest.exception.NotAuthorizedException;
17 |
18 | @Provider
19 | public class ResourceAuthFilter implements ContainerRequestFilter {
20 |
21 | @Override
22 | public void filter(ContainerRequestContext containerRequestContext) throws IOException {
23 |
24 | UriInfo info = containerRequestContext.getUriInfo();
25 | if (info.getPath().contains("user/login")) {
26 | return;
27 | }
28 |
29 | if (!isAuthTokenValid(containerRequestContext)) {
30 | // throw new NotAuthorizedException("You Don't Have Permission");
31 | containerRequestContext.abortWith(Response
32 | .seeOther(URI.create("/tastjava/user/login")).build());
33 | }
34 |
35 | return;
36 |
37 | }
38 |
39 | private boolean isAuthTokenValid(ContainerRequestContext containerRequestContext) {
40 | Map cookies = containerRequestContext.getCookies();
41 |
42 | if (cookies.get("jwt-authToken") != null) {
43 | String authToken = cookies.get("jwt-authToken").getValue();
44 | Logger.info(authToken);
45 | Integer uid = JWTProvider.verifyToken(authToken).getClaim("uid").asInt();
46 | Logger.info(uid);
47 | return true;
48 | }
49 | return false;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/service/UserService.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.service;
2 |
3 | import cn.xujiajun.tastjava.dao.UserDAO;
4 | import cn.xujiajun.tastjava.entity.User;
5 |
6 | import java.util.List;
7 |
8 | public class UserService {
9 | private UserDAO userDAO;
10 |
11 | public List GetUsers() {
12 | return this.userDAO.GetUsers();
13 | }
14 |
15 | public User GetUser(int id) {
16 | // return this.userDAO.GetUser();
17 | return this.userDAO.GetUser2(id);
18 | }
19 |
20 | /**
21 | * @return the userDAO
22 | */
23 | public UserDAO getUserDAO() {
24 | return userDAO;
25 | }
26 |
27 | /**
28 | * @param userDAO the userDAO to set
29 | */
30 | public void setUserDAO(UserDAO userDAO) {
31 | this.userDAO = userDAO;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/util/PropsUtil.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.util;
2 |
3 | import org.pmw.tinylog.Logger;
4 |
5 | import java.io.FileNotFoundException;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.util.Properties;
9 |
10 | public final class PropsUtil {
11 |
12 | /**
13 | * 加载属性文件
14 | */
15 | public static Properties loadProps(String fileName) {
16 | Properties props = null;
17 | InputStream is = null;
18 | try {
19 | is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
20 | if (is == null) {
21 | throw new FileNotFoundException(fileName + " file is not found");
22 | }
23 | props = new Properties();
24 | props.load(is);
25 | } catch (IOException e) {
26 | Logger.error("load properties file failure", e);
27 | } finally {
28 | if (is != null) {
29 | try {
30 | is.close();
31 | } catch (IOException e) {
32 | Logger.error("close input stream failure", e);
33 | }
34 | }
35 | }
36 | return props;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/cn/xujiajun/tastjava/util/StrUtil.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.util;
2 |
3 | public class StrUtil {
4 |
5 | public static boolean isBlank(String str) {
6 | return str == null || str.trim().length() == 0;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/resources/beans.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/main/resources/config.properties:
--------------------------------------------------------------------------------
1 | jdbc.driver=com.mysql.jdbc.Driver
2 | jdbc.url=jdbc:mysql://localhost:3306/test
3 | jdbc.username=root
4 | jdbc.password=123
--------------------------------------------------------------------------------
/src/main/resources/jwt.properties:
--------------------------------------------------------------------------------
1 | jwt.secret=tastjavasecret
--------------------------------------------------------------------------------
/src/main/resources/mybatis/Configuration.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/main/resources/mybatis/mapper/UserMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
--------------------------------------------------------------------------------
/src/main/resources/tinylog.properties:
--------------------------------------------------------------------------------
1 | tinylog.writer=file
2 | tinylog.writer.filename=/Users/xujiajun/Documents/tastjava/log.txt
3 | tinylog.level=info
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Archetype Created Web Application
7 |
8 |
9 | jerseyServlet
10 | org.glassfish.jersey.servlet.ServletContainer
11 |
12 | jersey.config.server.provider.packages
13 | cn.xujiajun.tastjava
14 |
15 | 1
16 |
17 |
18 | jerseyServlet
19 | /*
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World!
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/test/java/cn/xujiajun/tastjava/rest/HelloResourceTest.java:
--------------------------------------------------------------------------------
1 | package cn.xujiajun.tastjava.rest;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import javax.ws.rs.client.Client;
6 | import javax.ws.rs.client.ClientBuilder;
7 | import javax.ws.rs.client.WebTarget;
8 | import javax.ws.rs.core.MediaType;
9 |
10 | import org.junit.jupiter.api.Test;
11 |
12 | public class HelloResourceTest {
13 | private static final String REST_URI = "http://localhost:8080/tastjava/hi";
14 |
15 | private Client client = ClientBuilder.newClient();
16 |
17 | @Test
18 | public void sayHelloWordTest() {
19 | WebTarget target = client.target(REST_URI);
20 | String response = target.request(MediaType.TEXT_PLAIN_TYPE).get(String.class);
21 | assertEquals("OK", response);
22 | }
23 |
24 | @Test
25 | public void sayHelloNameTest() {
26 | WebTarget target = client.target(REST_URI);
27 | WebTarget targetUpdated = target.path("/tastjava");
28 | String response = targetUpdated.request(MediaType.TEXT_PLAIN_TYPE).get(String.class);
29 | assertEquals("OK", response);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------