概述 性能调优准则 1. 不要在没有必要的时候做性能调优 在大多数情况下,过早进行性能优化会占用大量时间,并使代码难以阅读和维护。更糟糕的是,这些优化通常不会带来任何好处,因为您花费大量时间来优化应用程序的非关键部分。
2. 使用分析器来查找真正的瓶颈 3. 为整个应用程序创建一个性能测试SuitCase 4. 先进行最大的瓶颈上工作 5. 使用StringBuilder来连接字符串 6. 在一个语句中使用+连接字符串 7. 尽可能使用基本数据 8. 尽量避免使用BigInteger和BigDecimal 9. 检查当前日志级别 正确的写法应该是这样的:
1 2 3 if (log.isDebugEnabled()) { log.debug("User [" + userName + "] called method X with [" + i + "]" ); }
10. 使用Apache Commons的StringUtils.Replace来替代String.replace 11. 缓存开销量较大的资源,如数据库连接等 编程进阶 1. 阅读源代码 搞清楚以下4个问题:
1 2 3 4 A、源代码是要解决什么问题? B、源代码是通过什么原理实现? C、它采用了哪些接口、类? D、为什么采用这些接口和类?
2. 多参与项目 通过项目的细节,你也可以查缺补漏,找到自己知识技能薄弱的环节。
3. 问题指引你进阶之路 尽量以问题为导向,这可以让你的思考和理解聚焦,而不至于分散。
4. 编程思想驾驭代码 可以边学边用《Effective Java》中的原理
5. Java程序员进阶书单 《Java编程思想》、《深入剖析Tomcat》、《深入理解Java虚拟机》、《JavaScript编程全解》、《Java程序性能优化》
Spring Spring MVC 1. 原理 配置阶段 引入
1 2 3 4 5 6 7 8 web.xml application.xml @Controller @Service @Autowired @RequestMapping @RequestParmter @ModelAndView
使用阶段 浏览器发送请求
1 2 3 doGet、doPost 根据url找对应的Method 通过反射调用和输出返回结果
2. 手写mvc代码 提升对框架设计原理的理解
提高解决问题的效率
web.xml 添加servlet
1 2 引入application.properties文件 scanPackage=com.xxx.demo //扫描包路径下的所有类
添加与新建servlet对应的servlet-mapping
servlet对应的java类 继承J2EE自带的HttpServlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 public class DisptcherServlet extends HttpServlet { private Properties p = new Properties (); private List<String> classNames = new ArrayList <String>(); private Map<String,Object> ioc = new HashMap <String,Object>(); private Map<String,Method> handlerMapping = new HashMap <String,Method>(); protected void doGet (HttpServletRequest req, HttpServletResponse resp) { this .doGet(req, resp); } protected void doPost (HttpServletRequest req, HttpServletResponse resp) { doDispatch(req, resp); } private void doDispatch (HttpServletRequest req, HttpServletResponse resp) { String url = req.getRequestURI(); String contextPath = req.getContextPath(); url = url.replace(contextPath,"" ).replaceAll("/*" ,"/" ); if (!handlerMapping.containsKey(url)){ resp.getWriter().write("404 Not Found" ); return ; } Method method = handlerMapping.get(url); } @Override public void init (ServletConfig config) throws ServletException{ doLoadConfig(config.getInitParameter("contextConfigLocation" );); doScanner(p.getProperty("scanPackage" )); doInstance(); doAutowired(); initHandlerMapping(); do ; } private void doLoadConfig (String path) { InputStream is = this .getClass().getClassLoader().getResourceAsStream(path); p.load(is); is.close(); } private void doScanner (String packageName) { URL url = this .getClass().getClassLoader().getResource("/" + packageName.replaceAll("\\." ,"/" )); File dir = new File (url.getFile()); for (File file : dir.listFiles()){ if (file.isDirectory()){ doScanner(packageName + "." + file.getName()); }else { classNames.add(packageName + "." + file.getName().replace(".class" ,"" )); } } } private void doInstance () { if (classNames.isEmpty())return ; for (String className : classNames){ Class<?> clazz = Class.forName(className); if (class.isAnnotationPresent(Controller.class)){ String beanName = clazz.getSimpleName(); ioc.put(beanName, clazz.newInstance()); }else if (class.isAnnotationPresent(Service.class)){ Service service = clazz.getAnnotation(Service.class); String beanName = service.value(); if ("" .equals(beanName.trim())){ ioc.put(beanName, clazz.newInstance()); }else { beanName = lowerFirst(clazz.getSimpleName()); ioc.put(beanName, clazz.newInstance()); } class<?> interfaces = clazz.getInterfaces(); for (Class<?> i : interfaces){ ioc.put(i.getName(), clazz.newInstance()); } } } } private void doAutowired () { if (ioc.isEmpty()) return ; for (Entry<String,Object> entry:ioc.entrySet()){ Field[] fields = entry.getValue().getClass().getDeclaredFields(); for (Field field: fields){ if (!field.isAnnotationPresent(Autowired.class)continue ; Autowired autowired = field.getAnnotation(Autowired.class); String beanName = autowired.value().trim(); if ("" .equals(beanName.trim())){ beanName = field.getType.getName(); } field.setAccessible(true ); field.set(entry.getValue(),ioc.get(beanName)); } } } private void initHandlerMapping () { if (ioc.isEmpty())return ; for (Entry<String,Object> entry : ioc.entrySet()){ Class<?> clazz = entry.getValue().getClass(); if (clazz.isAnnotationPresent(Controller.class)){ continue ; } String baseUrl = "" ; if (clazz.isAnnotationPresent(RequestMapping.class)){ RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class); baseUrl = requestMapping.value(); } Method[] methods = clazz.getMethods(); for (Method method:methods){ if (!method.isAnnotationPresent(RequestMapping.class)continue ; RequestMapping requestMapping = method.getAnnotation(RequestMapping.class); String mappingUrl = "/" + baseUrl + "/" + requestMapping.value().replaceAll("/*" ,"/" ); handlerMapping.put(mappingUrl, method); System.out.println("Mapping : " + mappingUrl + method); } } } }
添加注解类 Controller
1 2 3 4 5 6 7 package com.xxx.annotation;@Documented @Target(ElementType.TYPE) @Retention(TetentionPolicy.RUNTIME) public @interface Controller { String value () default "" ; }
RequestMapping
1 2 3 4 5 6 @Documented @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(TetentionPolicy.RUNTIME) public @interface RequestMapping { String value () default "" ; }
RequestParam
1 2 3 4 5 6 @Documented @Target({ElementType.PARAMETER) @Retention(TetentionPolicy.RUNTIME) public @interface RequestParam { String value () default "" ; }
Service
1 2 3 4 5 6 @Documented @Target(ElementType.TYPE) @Retention(TetentionPolicy.RUNTIME) public @interface Service { String value () default "" ; }
Autowired
1 2 3 4 5 6 @Documented @Target(ElementType.RIELD) @Retention(TetentionPolicy.RUNTIME) public @interface Autowired { String value () default "" ; }
使用注解 DemoService
1 2 3 4 5 6 @Service public class DemoService { public String get (String name) { return name + "!!!!!!" ; } }
DemoAction
1 2 3 4 5 6 7 8 9 10 11 12 @Controller @RequestMapping("/web") public class DemoAction { @Autowired DemoService demoService; @RequestMapping("/get.json") public void get (HttpServletRequest req, HttpServletResponse resp, @RequestParam("name") String name) { String result = demoService.get(name); resp.getWriter().write(result); } }
启动服务,访问http://localhost:8080/web/get.json?name=john
spring-boot 1. spring-boot-starter-security模块默认密码 Boot会为你提供一个默认的用户账号user和默认角色USER,并且会在应用启动的时候在控制台上输出随机生成的密码。
2. spring-boot-actuator 提供更多面向生产环境的支持,安全,日志,管理,审计。
1 2 3 4 5 6 7 8 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-actuator</artifactId > </dependency > <dependency > <groupId > org.jolokia</groupId > <artifactId > jolokia-core</artifactId > </dependency >
1 2 3 4 5 6 7 8 9 10 management.port = # defaults to 'server.port' management.address = # bind to a specific NIC management.context-path = # default to '/' management.add-application-context-header = # default to true management.security.enabled =true # enable security management.security.role =ADMIN # role required to access the management endpoint management.security.sessions =stateless # session creating policy to use (always, never, if_required, stateless) management.context-path =/actuator
3. spring-boot
下载eclipse mars
eclipse-jee-mars-R-win32-x86_64.zip
JDK1.8
参考http://spring.io/guides
运行,Goals spring-boot:run
断点调试,Profiles -Drun.jvmArguments=”-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005”
hateoas Accept: application/json, application/xml 返回例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 { "_embedded" : { "bookmarkResourceList" : [ { "bookmark" : { "id" : 213 , "uri" : "http://bookmark.com/1/mpollack" , "description" : "A description" } , "_links" : { "bookmark-uri" : { "href" : "http://bookmark.com/1/mpollack" } , "bookmarks" : { "href" : "http://localhost:9008/mpollack/bookmarks" } , "self" : { "href" : "http://localhost:9008/mpollack/bookmarks/213" } } } , { "bookmark" : { "id" : 214 , "uri" : "http://bookmark.com/2/mpollack" , "description" : "A description" } , "_links" : { "bookmark-uri" : { "href" : "http://bookmark.com/2/mpollack" } , "bookmarks" : { "href" : "http://localhost:9008/mpollack/bookmarks" } , "self" : { "href" : "http://localhost:9008/mpollack/bookmarks/214" } } } ] } }
为什么HATEOAS?
1)降低客户端编程错误。如下:访问uri全路径都返回了,直接使用即可,不用自己拼uri了
1 2 3 "bookmarks" : { "href" : "http://localhost:9008/mpollack/bookmarks" } ,
2)降低无效的状态迁移请求。只有当前状态下有效的状态变迁请求的URI会返回,其他无效的不会返回
3)渐进试改进并且不破坏(非必要的)旧客户端。服务器端严格控制后加的功能不破坏之前的行为,你可以合理快速的改进 API而不破坏所有客户端
Post模拟工具fiddler
spring boot 基础 1. aop 面向切面,提供切面注入的机制,通过这种方式,在业务运行中将定义好的切面通过切入点绑定到业务中,以实现将一些特殊的逻辑绑定到此业务中
aop名称
切面(Aspect):一个关注点的模块化,这个关注点可能会横切多个对象。在Spring AOP中,切面可以使用基于模式或者基于@Aspect注解的方式来实现。
连接点(Joinpoint):在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在Spring AOP中,一个连接点总是表示一个方法的执行。
通知(Advice):在切面的某个特定的连接点上执行的动作。其中包括了”around”、”before”和”after”等不同类型的通知。许多AOP框架(包括Spring)都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链。
切入点(Pointcut):匹配连接点的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。
使用spring AOP实现一个拦截器
http://blog.csdn.net/clementad/article/details/52035199
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 1 、引入依赖:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> 2 、创建拦截器类 @Aspect @Component public class ControllerInterceptor { @Pointcut("execution(* com.xjj.web.controller..*(..)) and @annotation(org.springframework.web.bind.annotation.RequestMapping)") public void controllerMethodPointcut () {} @Around("controllerMethodPointcut()") public Object Interceptor (ProceedingJoinPoint pjp) { long beginTime = System.currentTimeMillis(); MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); String methodName = method.getName(); Set<Object> allParams = new LinkedHashSet <>(); logger.info("请求开始,方法:{}" , methodName); Object result = null ; Object[] args = pjp.getArgs(); for (Object arg : args){ if (arg instanceof Map<?, ?>) { @SuppressWarnings("unchecked") Map<String, Object> map = (Map<String, Object>) arg; allParams.add(map); }else if (arg instanceof HttpServletRequest){ HttpServletRequest request = (HttpServletRequest) arg; result = new JsonResult (ResultCode.NOT_LOGIN, "该操作需要登录!去登录吗?\n\n(不知道登录账号?请联系老许。)" , null ); Map<String, String[]> paramMap = request.getParameterMap(); if (paramMap!=null && paramMap.size()>0 ){ allParams.add(paramMap); } }else if (arg instanceof HttpServletResponse){ }else { } } try { if (result == null ){ result = pjp.proceed(); } } catch (Throwable e) { logger.info("exception: " , e); result = new JsonResult (ResultCode.EXCEPTION, "发生异常:" +e.getMessage()); } if (result instanceof JsonResult){ long costMs = System.currentTimeMillis() - beginTime; logger.info("{}请求结束,耗时:{}ms" , methodName, costMs); } return result; } }
2. IOC(DI) 控制反转(IOC)和依赖注入(DI)的区别
http://blog.csdn.net/doris_crazy/article/details/18353197
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 (1)参与者都有谁: 一般有三方参与者,一个是某个对象;一个是IoC/DI的容器;另一个是某个对象的外部资源。 又要名词解释一下,某个对象指的就是任意的、普通的Java对象; IoC/DI的容器简单点说就是指用来实现IoC/DI功能的一个框架程序;对象的外部资源指的就是对象需要的,但是是从对象外部获取的,都统称资源,比如:对象需要的其它对象、或者是对象需要的文件资源等等。 (2)谁依赖于谁: 当然是某个对象依赖于IoC/DI的容器 (3)为什么需要依赖: 对象需要IoC/DI的容器来提供对象需要的外部资源 (4)谁注入于谁: 很明显是IoC/DI的容器 注入 某个对象 (5)到底注入什么: 就是注入某个对象所需要的外部资源 (6)谁控制谁: 当然是IoC/DI的容器来控制对象了 (7)控制什么: 主要是控制对象实例的创建 (8)为何叫反转: 反转是相对于正向而言的,那么什么算是正向的呢?考虑一下常规情况下的应用程序,如果要在A里面使用C,你会怎么做呢?当然是直接去创建C的对象,也就是说,是在A类中主动去获取所需要的外部资源C,这种情况被称为正向的。那么什么是反向呢?就是A类不再主动去获取C,而是被动等待,等待IoC/DI的容器获取一个C的实例,然后反向的注入到A类中。 依赖注入和控制反转是对同一件事情的不同描述,从某个方面讲,就是它们描述的角度不同。 依赖注入是从应用程序的角度在描述,可以把依赖注入描述完整点:应用程序依赖容器创建并注入它所需要的外部资源; 而控制反转是从容器的角度在描述,描述完整点:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。 反射 程序运行状态时,对于任意一个类,都能够知道这个类的所有属性和方法(包括私有),对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态类型信息及动态调用对象方法的功能叫做反射机制; http://blog.csdn.net/it_man/article/details/4402245 通常,每个对象在使用他的合作对象时,自己均要使用像new object() 这样的语法来完成合作对象的申请工作。你会发现:对象间的耦合度高了。而IOC的思想是:Spring容器来实现这些相互依赖对象的创建、协调工作。 比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。 依赖注入的思想也很简单,它是通过反射机制实现的,在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中。 首先实例化一个类 public static Object newInstance(String className) { Class<?> cls = null; Object obj = null; try { cls = Class.forName(className); obj = cls.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } return obj; } 接着它将这个类的依赖注入进去 public static void setProperty(Object obj, String name, String value) { Class<? extends Object> clazz = obj.getClass(); try { String methodName = returnSetMthodName(name); Method[] ms = clazz.getMethods(); for (Method m : ms) { if (m.getName().equals(methodName)) { if (m.getParameterTypes().length == 1) { Class<?> clazzParameterType = m.getParameterTypes()[0]; setFieldValue(clazzParameterType.getName(), value, m, obj); break; } } } } catch (Exception e) { throw new RuntimeException(e); } } 最后它将这个类的实例返回给我们,我们就可以用了。
实战 spring boot 性能优化 http://blog.oneapm.com/apm-tech/385.html
1. 组件自动扫描带来的问题 有三方面的影响:
会导致项目启动时间变长。当启动一个大的应用程序,或将做大量的集成测试启动应用程序时,影响会特别明显。
会加载一些不需要的多余的实例(beans)。
会增加 CPU 消耗。
解决方案:
移除 @SpringBootApplication 和 @ComponentScan 两个注解来禁用组件自动扫描 然后在我们需要的 bean 上进行显式配置:
1 2 3 4 5 6 7 8 9 10 11 @Configuration @EnableAutoConfiguration public class SampleWebUiApplication {@Bean public MessageController messageController (MessageRepository messageRepository) { return new MessageController (messageRepository); }
2. 避免组件自动扫描带来的问题 首先要知道我们需要的组件列表是哪些,可以用 -Ddebug 的方式来帮助我们明确地定位:
1 mvn spring-boot:run -Ddebug
1 2 3 4 5 6 7 8 9 10 11 12 … ========================= AUTO-CONFIGURATION REPORT ========================= Positive matches: ----------------- DispatcherServletAutoConfiguration - @ConditionalOnClass classes found: org.springframework.web.servlet.DispatcherServlet (OnClassCondition) - found web application StandardServletEnvironment (OnWebApplicationCondition) ...
拷贝 Positive matches 中列出的信息:
1 2 3 4 5 6 7 DispatcherServletAutoConfiguration EmbeddedServletContainerAutoConfiguration ErrorMvcAutoConfiguration HttpEncodingAutoConfiguration HttpMessageConvertersAutoConfiguration JacksonAutoConfiguration JmxAutoConfiguration
更新项目配置,显式地引入这些组件,引入之后,再运行一下应用确保没有错误发生:
1 2 3 4 5 6 7 8 9 @Configuration @Import({ DispatcherServletAutoConfiguration.class, EmbeddedServletContainerAutoConfiguration.class, ErrorMvcAutoConfiguration.class, HttpEncodingAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, }) public class SampleWebUiApplication {
不需要 JMX 和 WebSocket 功能,我就删掉了它们。
3. 将Servlet容器变成Undertow 从依赖信息里移除 Tomcat 配置:
1 2 3 4 5 6 <exclusions > <exclusion > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-tomcat</artifactId > </exclusion > </exclusions >
然后添加 Undertow:
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-undertow</artifactId > </dependency >
spring boot 远程调试 1 -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend =n
spring boot 打war包后 application.properties 配置文件需要放到war包的同一目录下,否则报Db配置错误。
thymeleaf里面的th和spring security结合进行页面权限配置 1 2 3 4 <li th:if ="${#authorization.expression('!isAuthenticated()')}" > <a href ="#" data-toggle ="modal" data-target ="#changePasswordModal" > 修改密码</a > </li >
spring 集成 h2数据库 1. application.properties 增加配置
1 2 3 4 5 6 7 spring.datasource.url =jdbc:h2:file:./database;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1 spring.jpa.hibernate.ddl-auto =update spring.jpa.show-sql =true spring.jpa.hibernate.naming-strategy =org.hibernate.cfg.EJB3NamingStrategy spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.H2Dialect
2. maven 配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 <?xml version="1.0" encoding="UTF-8" ?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > com</groupId > <artifactId > lottery</artifactId > <version > 1.0</version > <parent > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-parent</artifactId > <version > 1.2.5.RELEASE</version > </parent > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-jetty</artifactId > <scope > provided</scope > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-messaging</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-data-jpa</artifactId > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > </dependency > <dependency > <groupId > com.h2database</groupId > <artifactId > h2</artifactId > </dependency > </dependencies > <properties > <java.version > 1.7</java.version > </properties > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > </plugin > </plugins > </build > </project >
3. h2默认生成的表varchar是255长度 需要手工建立表
1 2 3 4 5 6 7 8 9 10 11 12 CREATE CACHED TABLE PUBLIC.TODAYINFO( ID BIGINT NOT NULL auto_increment, DATES VARCHAR (255 ) NOT NULL , FOCURS VARCHAR (5000 ), FUNDL VARCHAR (5000 ), SOIL VARCHAR (5000 ), SOILADVICE VARCHAR (5000 ), SSILVER VARCHAR (5000 ), SSILVERADVICE VARCHAR (5000 ), TECL VARCHAR (5000 ), UPDATETIME VARCHAR (255 ) )
使用工具:H2 Database Engine 1.4.185 绿色版
4. JpaRepository 1 2 3 4 5 6 7 8 public interface TodayInfoRepository extends JpaRepository <TodayInfo, Long> { @Query("SELECT o FROM TodayInfo o") Page<TodayInfo> getPage (Pageable page) ; @Query(nativeQuery = true, value = "SELECT a.* FROM `TodayInfo` a WHERE a.`dates` = :dates LIMIT 1") TodayInfo getUniqueByDates (@Param("dates") String dates) ; }
5. service 1 2 PageRequest pageRequest = new PageRequest (currPage, pageSize, Sort.Direction.DESC, "dates" );Page<TodayInfo> pages = todayInfoRepository.getPage(pageRequest);
杂记 1. 加载到配置文件,给入口类添加@ImportResource(“applicationContext.xml”) 2. spring security 官方文档 http://docs.spring.io/spring-security/site/docs/3.2.8.RELEASE/reference/htmlsingle/
Druid https://github.com/alibaba/druid
Druid 是阿里唯一使用的数据库连接池,支持双十一等最严苛的使用场景。是”为监控而生的数据库连接池”
1. 简介 https://www.cnblogs.com/niejunlei/p/5977895.html
1 2 3 4 5 6 7 8 9 10 11 Druid是Java语言中最好的数据库连接池。Druid能够提供强大的监控和扩展功能。 maven中央仓库: http://central.maven.org/maven2/com/alibaba/druid/ 配置maven <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > ${druid-version}</version > </dependency >
Dubbo2 http://dubbo.io/
https://github.com/alibaba/dubbo
dubbo是一个分布式的服务架构,可直接用于生产环境作为SOA服务框架。
实战 Eclipse添加阿里巴巴Java开发规约插件 http://blog.csdn.net/jiliang272/article/details/78269600
java 代码库 1. 获取访问者IP 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public static String getIpAddr (HttpServletRequest request) throws Exception{ String ip = request.getHeader("X-Real-IP" ); if (!StringUtils.isBlank(ip) && !"unknown" .equalsIgnoreCase(ip)) { return ip; } ip = request.getHeader("X-Forwarded-For" ); if (!StringUtils.isBlank(ip) && !"unknown" .equalsIgnoreCase(ip)) { int index = ip.indexOf(',' ); if (index != -1 ) { return ip.substring(0 , index); } else { return ip; } } else { return request.getRemoteAddr(); } }
2. Unicode转UTF-8代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 String str="\u7528\u6237\u540d\u6216\u5bc6\u7801\u4e0d\u6b63\u786e\uff0c\u8bf7\u91cd\u8bd5" ; System.out.println(decodeUnicode(str)); private static String decodeUnicode (String theString) { char aChar; int len = theString.length(); StringBuffer outBuffer = new StringBuffer (len); for (int x = 0 ; x < len;) { aChar = theString.charAt(x++); if (aChar == '\\' ) { aChar = theString.charAt(x++); if (aChar == 'u' ) { int value = 0 ; for (int i = 0 ; i < 4 ; i++) { aChar = theString.charAt(x++); switch (aChar) { case '0' : case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : value = (value << 4 ) + aChar - '0' ; break ; case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' : value = (value << 4 ) + 10 + aChar - 'a' ; break ; case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' : value = (value << 4 ) + 10 + aChar - 'A' ; break ; default : throw new IllegalArgumentException ( "Malformed \\uxxxx encoding." ); } } outBuffer.append((char ) value); } else { if (aChar == 't' ) aChar = '\t' ; else if (aChar == 'r' ) aChar = '\r' ; else if (aChar == 'n' ) aChar = '\n' ; else if (aChar == 'f' ) aChar = '\f' ; outBuffer.append(aChar); } } else outBuffer.append(aChar); } return outBuffer.toString(); }
问题汇总 1. mp4视频在html里,ios设备浏览器、微信等无法播放视频问题 不能用spring-boot来当容器启动服务,需要单独html,直接放到tomcat中,不用spring-boot项目
1 2 3 4 <video id ="video" style ="position: absolute; left: 63.3%;" controls ="controls" poster ="resources/images/H5-2.jpg" > <source src ="resources/video/meidui3.mp4" type ='video/mp4;' /> </video >
2. 关于在打包Jar文件时遇到的资源路径问题 http://www.cnblogs.com/fjdingsd/p/4680922.html
如果将资源同代码一起打包进Jar包中,当程序打包成可执行Jar包时
1 2 URL picUrl = this .getClass().getResource("/palette.gif" );Image image = new ImageIcon (picUrl).getImage();
如果资源路径前没有加”/“,则无论怎么点Jar包都不会有反应。
3. java代码写的中文(非从数据库读的中文)返回给客户端变乱码问题。 maven配置文件里要设置成用utf-8编译java代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <plugins > <plugin > <groupId > org.codehaus.mojo</groupId > <artifactId > tomcat-maven-plugin</artifactId > <version > 1.0</version > <configuration > <port > 9109</port > </configuration > </plugin > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-compiler-plugin</artifactId > <version > 3.3</version > <configuration > <source > 1.8</source > <target > 1.8</target > <encoding > utf8</encoding > </configuration > </plugin > </plugins >