28 Ekim 2021 Perşembe

POI Kullanımı

Maven
Şu satırı dahil ederiz
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi</artifactId>
  <version>4.1.2</version>
</dependency>
<dependency>
  <groupId>org.apache.poi</groupId>
  <artifactId>poi-ooxml</artifactId>
  <version>4.1.2</version>
</dependency>
Yazma
Her şey XSSWorkbook sınıfı etrafında dönüyor.
Örnek
Şöyle yaparız
ByteArrayOutputStream bos = new ByteArrayOutputStream();

try (Workbook workbook = new XSSFWorkbook()) {
  ...
} catch (Exception e) {
  ...
} finally {
  bos.close();
}
return bos.toByteArray();
Yazarken Font ve fontların kullanılacağı CellStyle nesnelerini oluşturmak gerekir. Şöyle yaparız
//setting up the basic styles for the workbook Font boldFont = getBoldFont(workbook); Font genericFont = getGenericFont(workbook); CellStyle headerStyle = getLeftAlignedCellStyle(workbook, boldFont); CellStyle currencyStyle = setCurrencyCellStyle(workbook); CellStyle centerAlignedStyle = getCenterAlignedCellStyle(workbook); CellStyle genericStyle = getLeftAlignedCellStyle(workbook, genericFont);
Daha sonra bir Sheet oluşturulur. Şöyle yaparız
String sheetName = ...
Sheet sheet = workbook.createSheet(sheetName);
Daha sonra bir başlık oluşturulur. Şöyle yaparız
int tempRowNo = 0;

//set spreadsheet titles
Row mainRow = sheet.createRow(tempRowNo++);

for (int i = 0; i < columnTitles.length; i++) {
  Cell columnTitleCell = mainRow.createCell(i);
  columnTitleCell.setCellStyle(headerStyle);
  columnTitleCell.setCellValue(columnTitles[i]);
}
Daha sonra veriyi sütunlar halinde yazarız. Şöyle yaparız
//looping the dataset
for (T record : data) {
  
  Row mainRow = sheet.createRow(tempRowNo++);
  Cell compositeNewCell = mainRow.createCell(cellIndex);
  cell.setCellValue(...);
  Hyperlink link = workbook.getCreationHelper().createHyperlink(HyperlinkType.URL);
  link.setAddress(...);
  cell.setHyperlink(link);
  ...
}
Tabi bu işleri yaparken bir sürü yardımcı metod gerekiyor. Bunları hep kodlamak lazım

Örnek
Elimizde şöyle bir kod olsun
public class ExcelGenerator {
  private List < Student > studentList = ...;
  private XSSFWorkbook workbook = new XSSFWorkbook();
  private XSSFSheet sheet;

  private void writeHeader() {
    sheet = workbook.createSheet("Student");
    Row row = sheet.createRow(0);
    CellStyle style = workbook.createCellStyle();
    XSSFFont font = workbook.createFont();
    font.setBold(true);
    font.setFontHeight(16);
    style.setFont(font);
    createCell(row, 0, "ID", style);
    createCell(row, 1, "Student Name", style);
    createCell(row, 2, "Email", style);
    createCell(row, 3, "Mobile No.", style);
  }
  private void createCell(Row row, int columnCount, Object valueOfCell,
    CellStyle style) {
    sheet.autoSizeColumn(columnCount);
    Cell cell = row.createCell(columnCount);
    if (valueOfCell instanceof Integer) {
      cell.setCellValue((Integer) valueOfCell);
    } else if (valueOfCell instanceof Long) {
      cell.setCellValue((Long) valueOfCell);
    } else if (valueOfCell instanceof String) {
      cell.setCellValue((String) valueOfCell);
    } else {
      cell.setCellValue((Boolean) valueOfCell);
    }
    cell.setCellStyle(style);
  }
  private void write() {
    int rowCount = 1;
    CellStyle style = workbook.createCellStyle();
    XSSFFont font = workbook.createFont();
    font.setFontHeight(14);
    style.setFont(font);
    for (Student record: studentList) {
      Row row = sheet.createRow(rowCount++);
      int columnCount = 0;
      createCell(row, columnCount++, record.getId(), style);
      createCell(row, columnCount++, record.getStudentName(), style);
      createCell(row, columnCount++, record.getEmail(), style);
      createCell(row, columnCount++, record.getMobileNo(), style);
    }
  }
}
Şöyle yaparız. Burada Excep direkt servlet cevabına yazılıyor
public class ExcelGenerator {
  
  public void generateExcelFile(HttpServletResponse response) throws IOException {
    writeHeader();
    write();
    ServletOutputStream outputStream = response.getOutputStream();
    workbook.write(outputStream);
    workbook.close();
    outputStream.close();
  }
}
Dosya İndirme
Örnek - SpringBoot
Şöyle yaparız
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

@Controller
public class UserController {

  @Autowired
  private UserService userService;

  @RequestMapping(method = RequestMethod.POST, value = "/download-users")
  public ResponseEntity downloadUsersExcel() {
    try {
      final byte[] data = userService.getUserXlsData();
      HttpHeaders header = new HttpHeaders();
      header.setContentType(MediaType.parseMediaType(
      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"));
      header.set(HttpHeaders.CONTENT_DISPOSITION, "inline; filename= users.xlsx");
      header.setContentLength(data.length);
      return new ResponseEntity<>(data, header, HttpStatus.OK);
    } catch (Exception e) {
      return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }
}


26 Ekim 2021 Salı

DbUtils

Giriş
Bu kütüphanede az sınıf var. Kullanması kolay. Tasarım açısından 2 çeşit API sağlıyor
1. JDBC kaynaklarını DbUtils'in yönettiği API. Bu kullanımda Connection, PreparedStatement ve ResultSet'i kütüphane kapatır.
2. Connection'ın dışarıdan verildiği API. Bu kullanımda Connection nesnesini bizim kapatmamız gerekir.

Kötü Tasarım
Bir seferinde Connection, PreparedStatement ve ResultSet'i sarmalayıp dışarı veren bir kütüphane görmüştüm. Bu sarmalanan nesneyi kapatmayı unutunca bir sürü resource leak oluyor ve "ORA-01000: Maximum Open Cursors Exceeded" hatası geliyordu.

Yani en güzeli, kaynakları kapatma işini kütüphanenin kendisinin yapması

Maven
Şu satırı dahil ederiz
<dependency>
  <groupId>commons-dbutils</groupId>
  <artifactId>commons-dbutils</artifactId>
  <version>1.6</version>
</dependency>
QueryRunner Sınıfı
insert metodu
Örnek
Şöyle yaparız
QueryRunner runner = new QueryRunner();
    String insertSQL
      = "INSERT INTO employee (firstname,lastname,salary, hireddate) "
        + "VALUES (?, ?, ?, ?)";

int numRowsInserted = runner.update(connection, insertSQL, "Leia", "Kane", 60000.60,
  new Date());
query metodu - String sql, ResultSetHandler<T> rsh, Object... params
Şöyle yaparız
// Create a ResultSetHandler implementation to convert the first row into an Object[].
ResultSetHandler<Object[]> h = new ResultSetHandler<>() {
  public Object[] handle(ResultSet rs) throws SQLException {
    ...
  }
};

// Create a QueryRunner that will use connections from the given DataSource
QueryRunner run = new QueryRunner(dataSource);

// Execute the query and get the results back from the handler
Object[] result = run.query("SELECT * FROM Person WHERE name=?", h, "John Doe");
query metodu - Connection + String sql, ResultSetHandler<T> rsh, Object... params
Şöyle yaparız
ResultSetHandler<Object[]> h = ... // Define a handler the same as above example

// No DataSource so we must handle Connections manually
QueryRunner run = new QueryRunner();
Connection conn = ... // open a connection try { Object[] result = run.query(conn, "SELECT * FROM Person WHERE name=?", h, "John Doe");
// do something with the result } finally { // Use this helper method so we don't have to check for null DbUtils.close(conn); }
update metodu
Örnek
Şöyle yaparız
double salary = 35000;

QueryRunner runner = new QueryRunner();
String updateSQL = "UPDATE employee SET salary = salary * 1.1 WHERE salary <= ?";
int numRowsUpdated = runner.update(connection, updateSQL, salary);
BeanListHandler Sınıfı
Şu satırı dahil ederiz
import org.apache.commons.dbutils.handlers.BeanListHandler;
Örnek
Elimizde şöyle bir kod olsun
public class EmployeeHandler extends BeanListHandler<Employee> {

  public EmployeeHandler() {
    super(Employee.class,
          new BasicRowProcessor(new BeanProcessor(getColumnsToFieldsMap())));
    // ...
  }
  protected Map<String, String> getColumnsToFieldsMap() {
    Map<String, String> columnsToFieldsMap = new HashMap<>();
    columnsToFieldsMap.put("FIRST_NAME", "firstName");
    columnsToFieldsMap.put("LAST_NAME", "lastName");
    columnsToFieldsMap.put("HIRED_DATE", "hiredDate");
    return columnsToFieldsMap;
  }

}
Şöyle yaparız
EmployeeHandler employeeHandler = new EmployeeHandler();

QueryRunner runner = new QueryRunner();
String query = "SELECT * FROM employee_legacy";
List<Employee> employees = runner.query(connection, query, employeeHandler);
MapListHandler Sınıfı
Şu satırı dahil ederiz
import org.apache.commons.dbutils.handlers.MapListHandler;
Örnek
Şöyle yaparız
MapListHandler beanListHandler = new MapListHandler();

QueryRunner runner = new QueryRunner();
List<Map<String, Object>> list = runner.query(connection, 
                                               "SELECT * FROM employee", 
                                               beanListHandler);


6 Ekim 2021 Çarşamba

Apache Shiro - Role-Based Access Control (RBAC) İçindir

Giriş
Açıklaması şöyle. Framework yani çatı olarak kullanılır.
Apache Shiro is a powerful and flexible open-source security framework that cleanly handles authentication, authorization, enterprise session management and cryptography.
Şeklen şöyle

Daha gelişmiş bir şekil şöyle

Bölümlerin amacı şöyle
Authentication: Sometimes referred to as ‘login’, this is the act of proving a user is who they say they are.
Authorization: The process of access control, i.e. determining ‘who’ has access to ‘what’.
Session Management: Managing user-specific sessions, even in non-web or EJB applications.
Cryptography: Keeping data secure using cryptographic algorithms while still being easy to use.
Maven
Spring ile kullanmak için şöyle yaparız
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.8.0</version>
</dependency>
Spring ile tümleşim için bir örnek burada