用Jersey构建RESTful服务9--Jersey+SQLServer+Hibernate4.3+Spring3.2+AngularJS

2014-07-31 Java Jersey REST AngularJS

一、总体说明

本例运行演示了用 Jersey 构建 RESTful 服务中,如何集成 angular,用MVC分层的方式访问 RESTful 服务。

二、环境

  • 1.上上文的项目 Demo7
  • 2.angular 库 ,本例为1.2.3 版本
  • 3.样式 bootstrap-3.1.1.min.js

三、配置

1.完成项目结构

配置 创建相应的目录结构

angularjs 、bootstrap 的js,css文件放别放入相应的目录,

在js目录下再创建 app.jscontroller.js

在partials目录下再创建 create.htmllist.htmldetail.html

完整目录结构如下结构

  1. list.html填入如下内容,主要是显示用户列表ng-repeat为 angularjs 迭代器 ``作用是数据绑定:
	 
	<div class="pull-right">
		<a href="#/create" class="btn btn-default" title="Create"><span class="glyphicon glyphicon-plus"></span></a>
	</div>
	<div class="page-header">
		<h3>Users</h3>
	</div>
	<hr />
	<li ng-repeat="user in users | filter:query | orderBy:orderProp"  >
	
		<div class="pull-right">
		   <a href="#/users/"  class="btn btn-xs btn-default" title="edit">
		   <span class="glyphicon glyphicon-pencil"></span></a>
		</div>
		<h4>userId: </h4>
		<p>userName:<a href="#/users/"></a>   Age:</p>
	<hr />
	</li>
	
	<hr />
  1. 修改create.html用来添加用户信息,ng-model是模型

	<div class="page-header">
		<h3>Create</h3>
	</div>
	
	<form role="form" name="userForm">
  
     <div class="row">&nbsp;</div>
     <div class="row" ng-class="{'has-error': userForm.userId.$invalid}">
      <div class="col-md-1">
        <i ng-show="userForm.url.$error.required" 
          class="glyphicon glyphicon-pencil"></i>
        <label for="urlInput">userId</label>
      </div>
      <div class="col-md-4">
        <input 
          type="test" 
          class="form-control" id="urlInput"
          name="userId" ng-model="user.userId" required> 
      </div>
    </div>
    <div class="row">&nbsp;</div>
    
    <div class="row" ng-class="{'has-error': userForm.userName.$invalid}">
      <div class="col-md-1">
        <i ng-show="userForm.userName.$error.required" 
          class="glyphicon glyphicon-pencil"></i>
        <label for="nameInput">userName</label>
      </div>
      <div class="col-md-4">
        <input 
          type="text" 
          class="form-control error" id="nameInput"
          name="userName" 
          ng-model="user.userName" 
          required> 
      </div>      
    </div>
    
    <div class="row">&nbsp;</div>
    <div class="row" ng-class="{'has-error': userForm.url.$invalid}">
      <div class="col-md-1">
        <i ng-show="userForm.url.$error.required" 
          class="glyphicon glyphicon-pencil"></i>
        <label for="urlInput">age</label>
      </div>
      <div class="col-md-4">
        <input 
          type="text" 
          class="form-control" id="urlInput"
          name="age" ng-model="user.age" required>
      </div>
    </div>

    <div class="row" ng-hide="showConfirm">
      <div class="col-md-5">
        <a href="#users" class="btn">Cancel</a>
        <button 
          ng-click="add()" 
          ng-disabled="isClean() || userForm.$invalid"
          class="btn btn-primary">Save</button>
 
      </div>
    </div>

  1. 修改detail.html用来显示用户信息并提供修改、删除等功能

  <form role="form" name="userForm">
  
     <div class="row">&nbsp;</div>
     <div class="row" ng-class="{'has-error': userForm.userId.$invalid}">
      <div class="col-md-1">
        <i ng-show="userForm.url.$error.required" 
          class="glyphicon glyphicon-pencil"></i>
        <label for="urlInput">userId</label>
      </div>
      <div class="col-md-4">
        <input 
          type="test" 
          class="form-control" id="urlInput"
          name="userId" ng-model="user.userId" required> 
      </div>
    </div>
    <div class="row">&nbsp;</div>
    
    <div class="row" ng-class="{'has-error': userForm.userName.$invalid}">
      <div class="col-md-1">
        <i ng-show="userForm.userName.$error.required" 
          class="glyphicon glyphicon-pencil"></i>
        <label for="nameInput">userName</label>
      </div>
      <div class="col-md-4">
        <input 
          type="text" 
          class="form-control error" id="nameInput"
          name="userName" 
          ng-model="user.userName" 
          fend-focus="focusUserNameeInput"
          required> 
      </div>      
    </div>
    <div class="row">&nbsp;</div>
    <div class="row" ng-class="{'has-error': userForm.url.$invalid}">
      <div class="col-md-1">
        <i ng-show="userForm.url.$error.required" 
          class="glyphicon glyphicon-pencil"></i>
        <label for="urlInput">age</label>
      </div>
      <div class="col-md-4">
        <input 
          type="text" 
          class="form-control" id="urlInput"
          name="age" ng-model="user.age" required>
      </div>
    </div>
    
    
    <div class="row" ng-hide="showConfirm">&nbsp;</div>

    <div class="row" ng-hide="showConfirm">
      <div class="col-md-5">
        <a href="#users" class="btn">Cancel</a>
        <button 
          ng-click="save()" 
          ng-disabled="isClean() || userForm.$invalid"
          class="btn btn-primary">Save</button>
        <button 
          ng-click="remove()"
          ng-show="user.userId" 
          class="btn btn-danger">Delete</button>
      </div>
    </div>

 
  </form>

  1. 修改index.html作为主页面,嵌入其他子页面,ng-app声明这个是模块,ng-controller说明他的控制器叫ListCtrl,ng-view用来存放子视图(页面)。

	<!doctype html>
	<html ng-app="appMain" ng-controller="ListCtrl">
	<head>
	    <meta charset="utf-8"/>
	 	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	    <link rel="stylesheet" href="css/bootstrap.min.css" type="text/css"/>
	</head>
	<body >
		<!-- navbar -->
	 	<div class="container ng-view"></div>
		<!-- footer -->
		<div id="footer" class="hidden-xs">
		  <div class="container">
		    <p class="text-muted">
		      Project Example - by <a href="http://www.waylau.com" target="_blank">www.waylau.com</a> | 
		      <a href="https://github.com/waylau" target="_blank">GitHub Project</a>
		    </p>
		  </div>
		</div>
	
		<script src="js/bootstrap-3.1.1.min.js"></script>
		<script src="js/angular-1.2.3.js"></script>
		<script src="js/angular-resource-1.2.3.js"></script>
		<script src="js/angular-route-1.2.3.js"></script>
		<script src="js/angular-cookies-1.2.3.js"></script>
		
	    <script src="js/app.js"></script>
	    <script src="js/controller.js"></script>
	</body>
	</html>

  1. 修改app.js ,声明模块appMain,提供路由功能,说明了调转到哪个页面,用哪个控制器

	angular.module('appMain', ['ngRoute']).config(['$routeProvider', function ($routeProvider) {
	    $routeProvider.
	        when('/users', {templateUrl: 'partials/list.html', controller: ListCtrl}).
	        when('/users/:userId', {templateUrl: 'partials/detail.html', controller: DetailCtrl}).
			when('/create', {
				templateUrl: 'partials/create.html',
				controller: CreateController
			}).
	        otherwise({redirectTo: '/users'});
	}]);
  1. 修改controller.js,控制器。主要是对业务逻辑的操作,常见的CURD功能,http访问RESTful接口,并且返回数据

	var url = 'http://localhost:8089/RestDemo/rest';
	
	function ListCtrl($scope, $http) {
	    $http.get( url + '/users' ).success(function(data) {
	        $scope.users = data;
	    });
	
	    $scope.orderProp = 'age';
	}
	
	function DetailCtrl($scope, $routeParams, $http) {
	 
	    $http.get( url + '/users/'+$routeParams.userId).success(function(data) {
	        $scope.user = data;
	    });
	    
		$scope.save = function() {
			$http.put( url + '/users',  $scope.user).
			success(function(data, status, headers, config){
				$location.path('/');
	        }).error(function(data, status, headers, config){
	            alert("error"+status);
	        }) ;
		};
		
		$scope.remove =  function(){
			$http({
				method:'DELETE',
				url: url + '/users/'+  $scope.user.userId ,
			})
			.success(function(data, status, headers, config){
				$location.path('/');
	        }).error(function(data, status, headers, config){
	            alert("error"+status);
	        }) ;
		};
	}
	 
	function CreateController($scope, $http) {
	 
	  
		$scope.add = function() {
			$http.post( url + '/users',  $scope.user).
			success(function(data, status, headers, config){
				$location.path('/');
	        }).error(function(data, status, headers, config){
	            alert("error"+status);
	        }) ;
		};
	}

四、运行

1.先运行项目

2.可以进行CURD操作

LIST

DETAIL

PS:本案例力求简单把 angularjs 访问 RESTful 服务展示出来,在Chrome,firefox,IE上做过测试。

本章源码jersey-demo9-sqlserver-hibernate-spring3-angularjs


用Jersey构建RESTful服务8--Jersey+SQLServer+Hibernate4.3+Spring3.2+jquery

2014-07-28 Java Jersey REST jQuery

#一、总体说明

本例运行演示了用 Jersey 构建 RESTful 服务中,如何集成 jQuery,用html作为客户端访问 RESTful 服务。

#二、环境

  • 1.上文的项目RestDemo
  • 2.jQuery 库 ,本例为1.7.1版本 #三、配置 配置
    1. 创建 jQuery 客户端的项目结构,在WebContent创建js,css两个目录,并把jQuery 库 放入js目录下,并在该目录下创建main,js空文件
  1. WebContent创建index.html:
	<!DOCTYPE HTML>
	<html>
	<head>
	<title>jquery Demo (人员管理系统)</title>
	<meta charset="utf-8"/>
	<link rel="stylesheet" href="css/styles.css" />
	 
	<script src="js/jquery-1.7.1.min.js"></script>
	<script src="js/main.js"></script>
	</head>
	
	<body>
		<div class="header">
	
			<button id="btnClear">Clear</button>
			<button id="btnRefreash">Refreash</button>
			更多实例访问:<a href="http://www.waylau.com" >www.waylau.com</a>
		</div>
	
	
		<div class="leftArea">
			<ul id="userList"></ul>
		</div>
	
		<form id="wineForm">
	
			<div class="mainArea">
	
				<label>Id:</label> <input id="userId" name="userId" type="text"  required/>
	
				<label>Name:</label> <input type="text" id="userName" name="userName" required> 
				<label>Age:</label> <input	type="text" id="age" name="age" required/>
				
				<button id="btnAdd">Add</button>
				<button id="btnSave">Save</button>
				<button id="btnDelete">Delete</button>
			</div>
	 
		</form>
	
	</body>
	</html>
  1. 修改main.js
	// The root URL for the RESTful services
	var rootURL = 'http://localhost:8089/RestDemo/rest/users';
	
	var currentUser;
	
	// Retrieve wine list when application starts 
	findAll();
	
	// Nothing to delete in initial application state
	$('#btnDelete').hide();
	
	$('#btnAdd').click(function() {
		addUser();
		return false;
	});
	
	$('#btnSave').click(function() {
	 
		updateUser();
		return false;
	});
	
	$('#btnClear').click(function() {
		newUser();
		return false;
	});
	
	
	$('#btnDelete').click(function() {
		deleteUser();
		return false;
	});
	
	$('#userList a').live('click', function() {
		findById($(this).data('identity'));
	});
	
	$('#btnRefreash').click(function() {
		findAll();
		return false;
	});
	 
	
	function newUser() {
		$('#btnDelete').hide();
		currentUser = {};
		renderDetails(currentUser); // Display empty form
	}
	
	function findAll() {
		console.log('findAll');
		$.ajax({
			type: 'GET',
			url: rootURL,
			dataType: "json", // data type of response
			success: renderList
		});
	}
	
	 
	function findById(id) {
		console.log('findById: ' + id);
		$.ajax({
			type: 'GET',
			url: rootURL + '/' + id,
			dataType: "json",
			success: function(data){
				$('#btnDelete').show();
	
				console.log('findById success: ' + data.userName);
				currentUser = data;
				renderDetails(currentUser);
			}
	 
		});
	}
	
	function addUser() {
		console.log('addUser');
		$.ajax({
			type: 'POST',
			contentType: 'application/json',
			url: rootURL,
			dataType: "json",
			data: formToJSON(),
			success: function(data, textStatus, jqXHR){
				alert('User created successfully');
				$('#btnDelete').show();
				$('#userId').val(data.userId);
			},
			error: function(jqXHR, textStatus, errorThrown){
				alert('addUser error: ' + textStatus);
			}
		});
	}
	
	function updateUser() {
		console.log('updateUser');
		$.ajax({
			type: 'PUT',
	
			contentType: 'application/json',
			url: rootURL,
			dataType: "json",
			data: formToJSON(),
			
			success: function(data, textStatus, jqXHR){
				alert('User updated successfully');
			},
			error: function(jqXHR, textStatus, errorThrown){
				alert('updateUser error: ' + textStatus);
			}
		});
	}
	
	function deleteUser() {
		console.log('deleteUser');
		$.ajax({
			type: 'DELETE',
			url: rootURL + '/' + $('#userId').val(),
			success: function(data, textStatus, jqXHR){
				alert('user deleted successfully');
			},
			error: function(jqXHR, textStatus, errorThrown){
				alert('delete user error');
			}
		});
	}
	
	function renderList(data) {
		// JAX-RS serializes an empty list as null, and a 'collection of one' as an object (not an 'array of one')
		var list = data == null ? [] : (data instanceof Array ? data : [data]);
	
		$('#userList li').remove();
		$.each(list, function(index, data) {
			$('#userList').append('<li><a href="#" data-identity="' + data.userId + '">'+data.userName+'</a></li>');
		});
	}
	
	function renderDetails(data) {
		$('#userId').val(data.userId);
		$('#userName').val(data.userName);
		$('#age').val(data.age);
	 
	}
	
	// Helper function to serialize all the form fields into a JSON string
	function formToJSON() {
		var userId = $('#userId').val();
		return JSON.stringify({
			"userId": userId == "" ? null : userId, 
			"userName": $('#userName').val(), 
			"age": $('#age').val() 
			});
	}
  1. css目录下创建styles.css文件
	* {
	  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
	  font-size: 18px;
	}
	
	.header {
		padding-top: 5px;
	 
	}
	
	.leftArea {
		position: absolute;
		left: 10px;
		top: 70px;
		bottom: 20px;
		width: 260px;
		border:solid 1px #CCCCCC;
		overflow-y: scroll;
	}
	
	.mainArea {
		position: absolute;
		top: 70px;
		bottom: 20px;
		left:300px;
		overflow-y: scroll;
		width:300px;
	}
	
	.rightArea {
		position: absolute;
		top: 70px;
		bottom: 20px;
		left:650px;
		overflow-y: scroll;
		width:270px;
	}
	
	ul {
		list-style-type: none;
		padding-left: 0px;
		margin-top: 0px;
	}
	
	li a { 
		text-decoration:none;
		display: block;
		color: #000000;
		border-bottom:solid 1px #CCCCCC;
		padding: 8px;
	}
	
	li a:hover {
		background-color: #4B0A1E;
		color: #BA8A92;
	}
	
	input, textarea {
	  border:1px solid #ccc;
	  min-height:30px;
	  outline: none;
	}
	
	.mainArea input {
	  margin-bottom:15px;
	  margin-top:5px;
	  width:280px;
	}
	
	textarea {
		margin-bottom:15px;
	  	margin-top:5px;
		height: 200px;
	  	width:250px;
	}
	
	label {
		display:block;
	}
	
	button {
		padding:6px;
	}
	
	
	#searchKey {
		width:160px;
	}

#四、运行 1.先运行项目

2.可以进行CURD操作 CURD

PS:本案例力求简单把jquery访问 RESTful 服务展示出来,代码只在Chrome上做过测试。

本章源码https://github.com/waylau/RestDemo/tree/master/jersey-demo8-sqlserver-hibernate-spring3-jquery


Spring 4.x 与可选的第三方库的关系

2014-07-26 Java Spring

1.Spring 4唯一的外部强制性的依库是 jakarta commons-logging

2.Spring 4与可选的第三方库一般只支持在2010年底或后来发布的版本:特别是,Hibernate 3.6+, EhCache 2.1+, Quartz 1.8+, Groovy 1.8+, and Joda-Time 2.0+。作为另外,Spring 4 要求最近的Hibernate Validator 4.3 +,并支持Jackson 2.0+Jackson 1.8/1.9只保留对 Spring 3.2 支持;现在是处在废弃的状态)。

3.Spring 4 对低支持到 JDK 6 update 18,在新项目中,最好用Java 7/8.

4.Java EE 6/7现在被认为是Spring 4的最低标准。建议使用JPA 2Servlet 3规范。为了兼容Google App Engine和老旧的应用,它可以部署 Spring4应用到servlet 2.5环境。然而,强烈建议用 Servlet 3+作为测试环境

5.Gradle作为项目构建工具

参考:spring-framework-reference (v4.0.6Release)


用Jersey构建RESTful服务7--Jersey+SQLServer+Hibernate4.3+Spring3.2

2014-07-25 Java Jersey REST Spring

#一、总体说明

本例运行演示了用 Jersey 构建 RESTful 服务中,如何集成 Spring3

#二、环境

  • 1.上文的项目RestDemo
  • 2.Spring及其他相关的jar ,导入项目 Spring及其他相关的jar

#三、配置

1.根目录下下创建 Spring 的配置文件applicationContext.xml; 配置如下:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context.xsd"
        >
    <!-- 激活那些已经在g容器里注册过的bean -->    
    <context:annotation-config></context:annotation-config>
    
	<!-- 在容器中注入bean -->
    <bean id="UserServiceImpl" class="com.waylau.rest.service.impl.UserServiceImpl"/>
	<bean id="UserDaoImpl" class="com.waylau.rest.dao.impl.UserDaoImpl"/>

</beans>

2.在com.waylau.rest.servicecom.waylau.rest.service.impl下分别增加 UserService 和 UserServiceImpl。

UserService.java

package com.waylau.rest.service;

import java.util.List;

import com.waylau.rest.bean.User;
 

/**
 * User Service 接口
 * @author waylau.com
 * 2014-7-25
 */
public interface UserService {
	
	public User getUserById(String id);

	public boolean deleteUserById(String id);

	public boolean createUser(User user);

	public boolean updateUser(User user);

	public List<User> getAllUsers();
}

UserServiceImpl.java

package com.waylau.rest.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import com.waylau.rest.bean.User;
import com.waylau.rest.dao.impl.UserDaoImpl;
import com.waylau.rest.service.UserService;
/**
 * User Service 接口实现
 * @author waylau.com
 * 2014-7-25
 */
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDaoImpl userDaoImpl;
    
	public UserServiceImpl() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public User getUserById(String id) {
		return userDaoImpl.getUserById(id);
	}

	@Override
	public boolean deleteUserById(String id) {
		return userDaoImpl.deleteUserById(id);
	}

	@Override
	public boolean createUser(User user) {
		return userDaoImpl.createUser(user);
	}

	@Override
	public boolean updateUser(User user) {
		return userDaoImpl.updateUser(user);
	}

	@Override
	public List<User> getAllUsers() {
		return userDaoImpl.getAllUsers();
	}

}

3.修改 UserResource.java

package com.waylau.rest.resources;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;

import org.springframework.beans.factory.annotation.Autowired;

import com.waylau.rest.bean.User;
import com.waylau.rest.service.impl.UserServiceImpl;

/**
 * 用户资源
 * @author waylau.com
 * 2014-7-26
 */
@Path("/users")
public class UserResource {
    private static final Logger LOGGER = Logger.getLogger(UserResource.class.getName());
    
    @Autowired
    private UserServiceImpl userServiceImpl;
    
    public UserResource() {
        LOGGER.fine("UserResource()");
    }
    
	/**
	 * 增加
	 * @param user
	 */
	@POST
    @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public void createUser(User user)
    {
		userServiceImpl.createUser(user);
    }
	
	/**
	 * 删除
	 * @param id
	 */
    @DELETE
    @Path("{id}")
    public void deleteUser(@PathParam("id")String id){
    	userServiceImpl.deleteUserById(id);
    }
    
    /**
     * 修改
     * @param user
     */
    @PUT
    @Consumes(MediaType.APPLICATION_XML)
    public void updateUser(User user){
		userServiceImpl.updateUser(user);
    }
 
    /**
     * 根据id查询
     * @param id
     * @return
     */
    @GET
    @Path("{id}")
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public User getUserById(@PathParam("id") String id){
    	User u = userServiceImpl.getUserById(id);
    	return u;
    }
   
    /**
     * 查询所有
     * @return
     */
    @GET
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public List<User> getAllUsers(){     
    	List<User> users = new ArrayList<User>();   
    	users = userServiceImpl.getAllUsers();
        return users;
    }
}

4.修改web.xml,插入

<module-name>RestDemo</module-name>

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:applicationContext.xml</param-value>
</context-param>

#四、运行 1.先运行项目

2.运行UserClient.java测试,控制台输出如下

****增加用户addUser****
****查询所有getAllUsers****
[{"userId":"002","userName":"sdfs","age":"23"},{"userId":"003","userName":"sdfs","age":"23"},{"userId":"004","userName":"sdfs","age":"23"},{"userId":"005","userName":"sdfs","age":"23"},{"userId":"006","userName":"Susan","age":"21"},{"userId":"007","userName":"sdfs","age":"23"},{"userId":"ds","userName":"ds","age":"ds"}]
****修改用户updateUser****
****根据id查询用户****
006Susan33
****查询所有getAllUsers****
[{"userId":"002","userName":"sdfs","age":"23"},{"userId":"003","userName":"sdfs","age":"23"},{"userId":"004","userName":"sdfs","age":"23"},{"userId":"005","userName":"sdfs","age":"23"},{"userId":"006","userName":"Susan","age":"33"},{"userId":"007","userName":"sdfs","age":"23"},{"userId":"ds","userName":"ds","age":"ds"}]
****删除用户****
****查询所有getAllUsers****
[{"userId":"002","userName":"sdfs","age":"23"},{"userId":"003","userName":"sdfs","age":"23"},{"userId":"004","userName":"sdfs","age":"23"},{"userId":"005","userName":"sdfs","age":"23"},{"userId":"007","userName":"sdfs","age":"23"},{"userId":"ds","userName":"ds","age":"ds"}]

本章源码(含jar包)https://github.com/waylau/RestDemo/tree/master/jersey-demo7-sqlserver-hibernate-spring3


使用maven编译Java项目

2014-07-17 Maven

#综述 本文演示了用Maven编译Java项目

#需要

  • 时间:15分钟
  • 文本编辑器或者IDE
  • JDK 6 或者更高版本

#创建项目 本例主要为了展示Maven,所以Java的项目力求简单。

#创建项目结构 选择一个项目目录,在 *nix系统上使用下面语句

mkdir -p src/main/java/hello

window下使用命令

mkdir src\main\java\hello

创建如下结构:

└── src
	└── main
    	└── java
        	└── hello

src/main/java/hello目录下创建Java文件HelloWorld.javaGreeter.java

src/main/java/hello/HelloWorld.java

package hello;

public class HelloWorld {
    public static void main(String[] args) {
        Greeter greeter = new Greeter();
        System.out.println(greeter.sayHello());
    }
}

src/main/java/hello/Greeter.java

package hello;

public class Greeter {
    public String sayHello() {
        return "Hello world!";
    }
}

现在项目完成,可以用Maven编译了。有关Maven的安装,可以参考Apache Maven 3.1.0 安装、部署、使用

#定义简单的Maven编译 首先,在项目的根目录下创建一个Maven项目定义文件pom.xml,该文件主要是说明项目的名称、版本和依赖库

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.springframework</groupId>
    <artifactId>gs-maven</artifactId>
    <packaging>jar</packaging>
    <version>0.1.0</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>hello.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

除了<packaging> 元素可选外,其他的元素是构成pom.xml 文件的最基本的元素了。它包括以下几个项目的配置:

  • <modelVersion> :POM 模块版本(通常是4.0.0).
  • <groupId> :项目所属的组织编号,通常用域名
  • <artifactId> 项目的名称(比如,JAR或者WAR的名称)
  • <version> 项目编译的版本号
  • <packaging> 项目打包形式,jar或者war

#编译Java代码 运行下面语句编译

mvn compile

编译完成的.class文件将会出现在target/classes目录下.如下图 编译Java代码

class

运行项目:

mvn exec:java -Dexec.mainClass="hello.HelloWorld"

输出如下: HelloWorld

如果不想直接运行.class文件,可以将其打包:

mvn package

打包完成后,会在target目录下生成一个JAR文件,文件名由<artifactId> 和 <version>组成。比如本例,将会根据pom.xml生成gs-maven-0.1.0.jar

gs-maven-0.1.0.jar

gs-maven-0.1.0.jar 如果你想安装您的项目的JAR文件到本地Maven仓库,那么你应该调用下面语句:

mvn install

此时,你的项目代码将会经过编译、测试、打包并拷贝到本地依赖库,提供给其他项目引用。

以上例子源码的地址https://github.com/waylau/maven-demo中的demo1

说到项目依赖,下面说下声明依赖

#声明依赖 上面的例子比较简单,没有用到其他库。但是真实的项目可能会引用(依赖)到很多其他库。

下面例子,依赖了Joda Time的库。

修改src/main/java/hello/HelloWorld.java

package hello;

import org.joda.time.LocalTime;

public class HelloWorld {
    public static void main(String[] args) {
		LocalTime currentTime = new LocalTime();
		System.out.println("The current local time is: " + currentTime);
		Greeter greeter = new Greeter();
		System.out.println(greeter.sayHello());
	}
}

现在运行mvn compile将会报错,因为没有声明依赖。在 <project> 节点下插入如下:

<dependencies>
    <dependency>
        <groupId>joda-time</groupId>
        <artifactId>joda-time</artifactId>
        <version>2.2</version>
    </dependency>
</dependencies>

声明依赖

这段内容就声明了项目的依赖。每个依赖节点<dependency>都由三个子节点组成:

  • <groupId> : 该依赖库所属的组织名称
  • <artifactId> : 依赖的库名
  • <version> : 依赖的库版本

在POM 4中,<dependency> 中还引入了<scope> ,它主要管理依赖的部署。目前<scope> 可以使用5个值:

  • compile,缺省值,适用于所有阶段,会随着项目一起发布。
  • provided,类似compile,期望JDK、容器或使用者会提供这个依赖。如servlet.jar。
  • runtime,只在运行时使用,如JDBC驱动,适用运行和测试阶段。
  • test,只在测试时使用,用于编译和运行测试代码。不会随项目发布。
  • system,类似provided,需要显式提供包含依赖的jar,Maven不会在Repository中查找它。

现在你运行mvn compile或者mvn package,Maven会自动下载相关依赖。

完整的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.springframework</groupId>
    <artifactId>gs-maven</artifactId>
    <packaging>jar</packaging>
    <version>0.1.0</version>

    <!-- tag::joda[] -->
    <dependencies>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.2</version>
        </dependency>
    </dependencies>
    <!-- end::joda[] -->

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>hello.HelloWorld</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

运行项目:

mvn exec:java -Dexec.mainClass="hello.HelloWorld"

输出如下: 运行项目

以上例子源码的地址https://github.com/waylau/maven-demo中的demo2

参考:http://spring.io/guides/gs/maven/

http://www.vineetmanohar.com/2009/11/3-ways-to-run-java-main-from-maven/


使用maven镜像

2014-07-16 Maven

#综述 用maven做项目,最郁闷的莫过于某些依赖库下载不了。被墙了,你懂的。使用maven镜像仓库及其重要,特别是国内的镜像,可以有效缓解被墙疼痛。

#常用的镜像

##国外镜像

ibiblio.org

<mirror>  
     <id>ibiblio</id>  
     <mirrorOf>central</mirrorOf>  
     <name>ibiblio Mirror of http://repo1.maven.org/maven2/</name>  
     <url>http://mirrors.ibiblio.org/pub/mirrors/maven2/</url>  
</mirror>  

jboss

<mirror>  
     <id>jboss-public-repository-group</id>  
     <mirrorOf>central</mirrorOf>  
     <name>JBoss Public Repository Group</name>  
     <url>http://repository.jboss.org/nexus/content/groups/public</url>  
</mirror>

repo2

<mirror>
  <id>repo2</id>
  <mirrorOf>central</mirrorOf>
  <name>Human Readable Name for this Mirror.</name>
  <url>http://repo2.maven.org/maven2/</url>
</mirror>

uk.maven.org

<mirror>
  <id>ui</id>
  <mirrorOf>central</mirrorOf>
  <name>Human Readable Name for this Mirror.</name>
 <url>http://uk.maven.org/maven2/</url>
</mirror>

##国内镜像

aliyun.com

    <id>nexus-aliyun</id>
    <mirrorOf>*</mirrorOf>
    <name>Nexus aliyun</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror> 

oschina.net(目前已经不能访问)

    <id>nexus-osc</id>
    <mirrorOf>*</mirrorOf>
    <name>Nexus osc</name>
    <url>http://maven.oschina.net/content/groups/public/</url>
</mirror>

net.cn(目前已经不能访问)

<mirror>
    <id>net-cn</id>
    <mirrorOf>central</mirrorOf>
    <name>Human Readable Name for this Mirror.</name>
    <url>http://maven.net.cn/content/groups/public/</url>	
 </mirror>

#使用镜像

使用 aliyun.com 镜像

在maven的settings.xml 文件里配置mirrors的子节点,添加如下 mirror

    <id>nexus-aliyun</id>
    <mirrorOf>*</mirrorOf>
    <name>Nexus aliyun</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public</url>
</mirror> 

使用 oschina.net 镜像

下文以oschina.net的镜像为例子.

1.Maven 的安装目录下的 conf 文件下有个settings.xml文件,编辑该文件

2.在<mirrors>中插入:

    <id>nexus-osc</id>
    <mirrorOf>*</mirrorOf>
    <name>Nexus osc</name>
    <url>http://maven.oschina.net/content/groups/public/</url>
</mirror>

3.这里是配置 Maven 的 mirror 地址指向OSChina 的 Maven 镜像地址。 在执行 Maven 命令的时候, Maven 还需要安装一些插件包,这些插件包的下载地址也让其指向 oschina.net 的 Maven 地址。在<profiles>中插入:

<profile>
    <id>jdk-1.4</id>
    <activation>
    <jdk>1.4</jdk>
    </activation>
    <repositories>
        <repository>
            <id>nexus</id>
            <name>local private nexus</name>
            <url>http://maven.oschina.net/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>nexus</id>
            <name>local private nexus</name>
            <url>http://maven.oschina.net/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</profile>

参考:http://maven.oschina.net/help.html


简单折线算法

2014-07-15 Data visualization

#一、综述 在做流程图软件时,折线必不可少。本文展示的是现有系统的简单折线实现。折线主要分为一折折线、二折折线。下面例子默认起点为“图1”,终点为“图2”,假设pt1,pt2为已知点,pt3,pt4为动态计算点。

#二、一折折线 一折折线

pt3 = ( pt2.x  , pt1.y )

#三、二折折线 ##1.pt1 在pt2的左侧 二折折线,pt1 在pt2的左侧

pt3 = ( pt1.x + ( pt2.x – pt1.x )*0.5 , pt1.y )
pt4 = ( pt1.x + ( pt2.x – pt1.x )*0.5 , pt2.y )

##2.pt1 在pt2的右侧 二折折线,pt1 在pt2的右侧

pt3 = ( pt2.x + ( pt1.x – pt2.x )*0.5 , pt1.y )
pt4 = ( pt2.x + ( pt1.x – pt2.x )*0.5 , pt2.y )

又一架梯子上墙利器--DNSCrypt

2014-07-09 Web

翻墙 #神马是DNSCrypt? 官方提法“DNSCrypt is a piece of lightweight software that everyone should use to boost online privacy and security. It works by encrypting all DNS traffic between the user and OpenDNS, preventing any spying, spoofing or man-in-the-middle attacks.”

可加密DNS流量,阻止常见的DNS攻击,如重放攻击、观察攻击、时序攻击、中间人攻击和解析伪造攻击,是防止DNS污染的绝佳工具。

#神马是DNS污染? 是指一些刻意制造或无意中制造出来的域名服务器分组,把域名指往不正确的IP地址。擦~不就是被“墙”了吗?

#DNSCrypt搞起来! DNSCrypt官方介绍页面:http://www.opendns.com/about/innovations/dnscrypt/

DNSCrypt最新下载地址:http://shared.opendns.com/dnscrypt/packages/windows-client/DNSCryptWin-v0.0.6.exe

安装运行后,亮绿灯 DNSCrypt

测试下https://www.flickr.com https://www.flickr.com

测试下https://www.facebook.com/ https://www.facebook.com/

测试下https://www.youtube.com 网速有点慢,今天的主脚竟然是涛哥和温总 https://www.youtube.com/