Spring jednoduše 2. díl

V předchozím dílu jsme pro získání instance použili metodu context.getBean(„myClass“).

MyClass mc1 = (MyClass) context.getBean("myClass");

Získá instanci na základě id, které je definováno v souboru beans.xml. Metoda getBean(String name) vrací Object, takže je nutné přetypování. Existují ale i další možnosti.

MyClass mc2 = context.getBean(MyClass.class, "myClass");

Tato metoda je stejná jako předchozí, jen vrací instanci třídy zadané jako parametr a tím pádem není nutné provádět přetypování jako v předchozím případě.

MyClass mc3 = context.getBean(MyClass.class);

Získá instanci dané třídy. V tomto případě stačí mít v beans.xml pouze následující definici (bez id).

   <bean class="cz.vitfo.spring01.MyClass">
       <property name="message" value="Hello World!"/>
   </bean>

Vysvětlení pojmů

Kontejner je komponenta, která v sobě obsahuje jinou komponentu a poskytuje jí nějakou službu.

Spring kontejner je kontejner, který zodpovídá za všechny beany (instance), které vytváří, a které poskytuje aplikaci. Je také zodpovědný, že beany (instance) budou k dispozici ve správný čas na správném místě. Aby toto mohl provádět, potřebuje konfiguraci. V našem případě to konfigurace v souboru beans.xml, ale Spring umožňuje i jiné formy konfigurace.

Bean je třída, která obsahuje proměnné, gettery a settery. Je to forma POJO (Plain Old Java Object).

Hašování retězce pomocí různých algoritmů v Javě

Nejdříve vysvětlení pojmů.

Hašovací funkce je matematická funkce (resp. algoritmus) pro převod vstupních dat do (relativně) malého čísla. Výstup hašovací funkce se označuje výtah, miniatura, otisk, fingerprint či hash (česky též někdy jako haš).
Mezi hlavní vlastnosti této funkce patří:

  • jakékoliv množství vstupních dat poskytuje stejně dlouhý výstup (otisk)
  • malou změnou vstupních dat dosáhneme velké změny na výstupu (tj. výsledný otisk se od původního zásadně na první pohled liší)
  • z hashe je prakticky nemožné rekonstruovat původní text zprávy (což je rozdíl oproti klasickému šifrování)
  • v praxi je vysoce nepravděpodobné, že dvěma různým zprávám odpovídá stejný hash, jinými slovy pomocí hashe lze v praxi identifikovat právě jednu zprávu (ověřit její správnost).

Hašování v základní variantě dovoluje testovat vstupní data na shodu, tedy rovnost. Nezachovává podobnost dat ani uspořádání. wiki

Zdůrazňuji, že jakékoliv množství vstupních dat poskytuje stejně dlouhý výstup a malou změnou vstupních dat dosáhneme velké změny na výstupu.

Pro hashování v Javě existuje třída MessageDigest. Digest v překladu v tomto kontextu znamená suma, souhrn. V rámci standardní Javy jsou k dispozici hašovací algoritmy MD5, SHA-1, SHA-256.

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

public class App {

	public static void main(String[] args) {
		String message = "Hello World!";
		
		try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
			MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
			
			byte[] md5Digest = md5.digest(message.getBytes());
			byte[] sha1Digest = sha1.digest(message.getBytes());
			byte[] sha256Digest = sha256.digest(message.getBytes());
			
			System.out.println(formatResult(md5Digest));
			System.out.println(formatResult(sha1Digest));
			System.out.println(formatResult(sha256Digest));
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
	}
	
	private static String formatResult(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		sb.append("Délka pole: ");
		sb.append(bytes.length);
		sb.append("\t");
		sb.append("Pole: ");
		sb.append(Arrays.toString(bytes));
		return sb.toString();
	}
}

MessageDigest potřebuje na vstupu pole bytů (message.getBytes()) a vrátí také pole bytů, která má ale předem danou délku (je jedno jak dlouhý text hašujete) a představuje otisk původního pole.

Rozdíl výsledku při změně jediného znaku (z Hello World! na Hallo World!) pro všechny tři algoritmy.

Délka pole: 16	Pole: [-19, 7, 98, -121, 83, 46, -122, 54, 94, -124, 30, -110, -65, -59, 13, -116]
Délka pole: 16	Pole: [98, 119, 56, -33, 57, 107, 57, -72, -69, -54, 87, 79, 122, 72, -72, 50]

Délka pole: 20	Pole: [46, -9, -67, -26, 8, -50, 84, 4, -23, 125, 95, 4, 47, -107, -8, -97, 28, 35, 40, 113]
Délka pole: 20	Pole: [65, 63, 96, -127, -42, 94, -26, 2, -115, 124, -43, -81, -110, 32, 39, 12, -125, 121, 61, -5]

Délka pole: 32	Pole: [127, -125, -79, 101, 127, -15, -4, 83, -71, 45, -63, -127, 72, -95, -42, 93, -4, 45, 75, 31, -93, -42, 119, 40, 74, -35, -46, 0, 18, 109, -112, 105]
Délka pole: 32	Pole: [85, 65, 51, 18, -114, -77, 16, 91, -101, -83, 102, 27, -115, 61, 17, -117, -53, -39, -47, 86, -115, -46, -5, 112, 8, 127, -119, 4, 27, 14, 3, -80]

Je vidět, že drobná změna vede k velmi rozdílnému výsledku každého ze zkoušený hašovacích algoritmů.

Zásobník v Javě

Třída Stack (zásobník) je datová stuktura, která funguje na principu LIFO (Last In First Out). Jedná se o kolekci objektů, kdy poslední vložený objekt je vybírán jako první (a první vložený jako poslední).

Vytvoříme si zásobník obsahující čtyři objekty.

Stack<Integer> stack = new Stack<Integer>();
stack.push(5);
stack.push(7);
stack.push(2);
stack.push(7);

Jedná se o kolekci, takže je možné ji procházet.

for (Integer i : stack) {
	System.out.println(i);
}

Pro přidání objektu na konec zásobníku se používá metoda push(). Pro získání posledně přidaného objektu se používají metody peek() a pop().

peek()

System.out.println(stack.peek());
System.out.println(stack.peek());

Výsledek (pořád vrací poslení objekt)

7
7
7
7
7

pop()

System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());

Výsledek

7
2
7
5
Exception in thread "main" java.util.EmptyStackException

Čtvrté volání metody pop() vrátí poslední objekt (první přidaný) a zásobník je prázdný. Pokud zavoláme pop() ještě jednou (na prázdném zásobníku) dostaneme chybu EmptyStackException.

Spring jednoduše 1. díl

Spring je obrovský ekosystém pokrývající rozsáhlou oblast programování. Základní funkcionalitou frameworku je Inversion of Control, což jednoduše řečeno znamená, že objekty, které potřebují další objekty, si tyto objekty nevytváří pomocí klíčového slova new sami, ale přenechávají tuto činnost Springu (Spring kontejneru). Ten je pak zodpovědný za vytváření objektů (za celý životní cyklus objektu od vzniku po zánik). Důvod pro tuto činnost je ten, že díky Springu nejsou komponenty těsně se sebou svázány (a je např. jednodušší vyměnit jednu implementaci za druhou).

Zde je struktura jednoduchého Maven projektu, používajícího Spring.

spring01
│   .classpath
│   .project
│   pom.xml
│
├───.settings
│       org.eclipse.core.resources.prefs
│       org.eclipse.jdt.core.prefs
│       org.eclipse.m2e.core.prefs
│
└───src
    ├───main
    │   └───java
    │       └───cz
    │           └───vitfo
    │               └───spring01
    │                       Main.java
    │                       MyClass.java
    │
    ├───resources
    │       beans.xml
    │
    └───test

Pokud odmažu soubory a složky, které nejsou důležité, vypadá projekt následovně.

spring01
│   pom.xml
│
└───src
    ├───main
    │   └───java
    │       └───cz
    │           └───vitfo
    │               └───spring01
    │                       Main.java
    │                       MyClass.java
    │
    └───resources
            beans.xml

Skládá se z souboru pom.xml, který slouží Mavenu a jsou v něm definovány závislosti na knihovách na Springu.

&<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>cz.vito</groupId>
	<artifactId>spring01</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>spring01</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>4.2.3.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.2.3.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>4.2.3.RELEASE</version>
		</dependency>
	</dependencies>
</project>e

Druhým nezbytným souborem je beans.xml (na názvu nezáleží, ale je zvykem ho pojmenovávat beans.xml). Tento soubor slouží jako konfigurace Springu (Spring kontejneru) a je v něm definováno, jak a jaké objekty má Spring vytvářet. V tomto příkladu je definována jediná beana s názvem (id) ‚myClass‘, která bude instancí třídy cz.vitfo.spring01.MyClass.

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="myClass" class="cz.vitfo.spring01.MyClass">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>

Nakonec zde ještě máme třídu MyClass

package cz.vitfo.spring01;

public class MyClass {

	private String message;

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}
}

a třídu s metodou main, která slouží jako vstupní bod programu.

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

package cz.vitfo.spring01;

public class Main 
{
    public static void main(String[] args) {
    	// beans.xml musí být na class path
		ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		
		MyClass mc = (MyClass) context.getBean("myClass");
		
		System.out.println(mc.getMessage());
	}
}

Pokud program spustíte (run ve třídě s metodou main), dostanete následující výpis do konzole.

Čvc 01, 2016 3:48:51 ODP. org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1f17ae12: startup date [Fri Jul 01 15:48:51 CEST 2016]; root of context hierarchy
Čvc 01, 2016 3:48:51 ODP. org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
Hello World!
Picked up JAVA_TOOL_OPTIONS: -Djava.vendor="Sun Microsystems Inc."

Pro nás nejdůležitější je řádek obsahující ‚Hello World!‘. Došlo ke spuštění programu a výpisu proměnné message Springem vytvořeného objektu mc.

Pokud jste dostali následující chybový výpis

Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [beans.xml]; nested exception is java.io.FileNotFoundException: class path resource [beans.xml] cannot be opened because it does not exist

ujistěte se, že soubor beans.xml skutečně existuje, a že je umístěn na classpath (např. v package src/resources).

V případě této chyby

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myClass' is defined

se ujistěte, že v beans.xml máte nadefinovánu beanu s id myClass a nedopustili jste se nějakého překlepu.

Jak zrušit varování Optional used as type for parameter v Idea IDE

Idea při commitu do gitu upozorňuje na to, že Optional<> je použit jako parameter metody.

idea_warnig_optional_used

Tohoto varování se můžete zbavit následujícím způsobem:
File -> Settings -> Editor -> Inspections -> rozbalit Java -> rozbalit Abstraction issues -> odčeknout ‚Optional‘ used as field or parameter type

idea_warnig_optional_used_02

Zdroj: http://stackoverflow.com/…used-as-field-or-parameter-type-warning-in-intelli

Využití místa na disku ve Windows 10

Máte málo místa na disku a zajímalo by vás, které soubory a aplikace ho zabírají nejvíce?

Nastavení (nejjednodušeji se zde dostanete přes lupu, kdy do vyhledávání napíšete ‚nastavení‘.

misto_na_disku_ve_windows_10_01

Úložiště (nejjednodušeji jej naleznete přes vyhledávací textové pole – viz obrázek)

misto_na_disku_ve_windows_10_02 misto_na_disku_ve_windows_10_03

Vyberte úložiště, které vás zajímá. V tomto případě jsem zvolil disk C. Zobrazí se vám grafické znázornění využití místa na tomto disku.

misto_na_disku_ve_windows_10_04

Rozklikněte oblast, která vás zajímá.

misto_na_disku_ve_windows_10_05

Přidání sloupce v PostgreSQL

Pokud máte existující tabulku a potřebujete do ní přidat sloupec a nechcete celou tabulku dropnout a vytvořit znovu, protože byste přišli o data, existuje v postgre příkaz ALTER TABLE ADD COLUMN.

Vytvoříme pokusnou tabulku.

create table pok (
	id	serial		not null,
	jmeno	varchar(100)	not null,

	primary key (id)
);

Přidáme do ní sloupec z názvem prijmeni a omezením (contraint) not null.

alter table pok
add column prijmeni varchar(100) not null;

Vložíme do tabulky dva záznamy.

insert into pok (jmeno, prijmeni) values
	('František', 'Koudelka'),
	('Jana', 'Nová');

Přidáme do tabulky sloupec narozen, který může být null.

alter table pok
add column narozen date;

Přidáme do tabulky sloupec prezdivka a jako výchozí hodnotu (pro ty které jsou null) použijeme řetězec lama.

alter table pok
add column prezdivka varchar(20) not null default 'lama';

Vložíme do tabulky další záznam.

insert into pok (jmeno, prijmeni, prezdivka) values
	('Tomáš', 'Nový', 'jouda');

Výsledek.

postres_pridani_sloupce

Vrácení smazaného souboru v Idea IDE

Pokud v Idea IDE smažete soubor, můžete tuto akci vrátit zpět pomocí lokální historie. Pravým tlačítkem na projekt -> Local History -> Show History.

idea_local_history

V tomto případě jsem smazal soubor pokus.sql.

idea_local_history02

Pokud chceme soubor vrátit -> pravým tlačítkem na soubor -> Revert Selection nebo na akci a Revert.

idea_local_history03

Pokud vyberete File -> Invalidate Caches / Restart, přijdete o lokální historii a tím pádem i o tuto možnost vrácení smazaného souboru.

Vyhledání speciálního znaku v kódu v Idea IDE

Pokud v potřebujete ve svém projektu vyhledávat, v Idea IDE k tomu slouží klávesová zkratka Ctrl + Shift + F (Edit -> Find -> Find in Path …).

idea_vyhledavani

Problém nastává v případě, že chcete vyhledávat text obsahující speciální znaky např. [, *, $, ), … Řešením je přidat před speciální znak zpětné lomítko \.

Takto byste např. v projektu vyhledali výskyt pole int.
int\[\]

A takto všechny dotazy do databáze obsahující *.
select \*