├── .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 | --------------------------------------------------------------------------------