Gobble up pudding

プログラミングの記事がメインのブログです。

MENU

フィボナッチ数列でメモ化

f:id:fa11enprince:20190413175245j:plain なんとなくC++をちょろっと書いてみたくなったので書いてみました。
いや、ほぼC言語だけど…。 それよりもWandboxがC++2aとかになってて…えぇ…C++11からかなりバージョン上がってるなぁ…という印象です。

#include <iostream>
#include <cstdlib>
#include <stdexcept>

#define CHECK(e) do { if (e < 0) { throw std::out_of_range("the number must be grater than or equal to 1"); } } while(0)

int x[] = {0, 1};  // fib(0) = 0, fib(1) = 1

/**
 * memoized fibonacci function
 */
int fib_memo(int e) {
    CHECK(e); 
    int ans = 0;
    for (int i = 0; i < e; ++i) {
        ans = x[i%2] + x[(i+1)%2];
        x[(i+1)%2] = ans;  // first, update 2nd index ...
    }
    return ans;
}

/**
 * recursive fibonacci function
 */
int fib_recv(int e) {
    CHECK(e);
    return e == 0 ? 0 : (e == 1 ? 1 : (fib_recv(e - 1) + fib_recv(e - 2)));
}

int main()
{
    using namespace std;
    ios::sync_with_stdio(false);
    try {
       cout << fib_memo(45) << endl;
       //cout << fib_recv(45) << endl;
    } catch (const out_of_range& e) {
       cerr << e.what() << endl;
    }
}

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

cpprefjpをのぞいたらC++11以降の記載がたくさん。。。 なんか見た目が結構変わった気がする…。

片手間でJavaScriptを書く際の定番の書き方メモ

f:id:fa11enprince:20171220162911j:plain ガシガシJavaScriptをかかないWebアプリで、比較的単純なJQueryだけのプロジェクトのときに極力名前空間を汚さず大してめんどくさくなく書く方法のメモ 見返したらただの感想文になってしまった。

とりあえず (function($) { ... })(jQuery);で引数ありの即時関数で包んでその中に愚直に処理を書くのが楽そう。 プロトタイプベースのオブジェクト指向でガシガシ書くのはオワコンっぽいんでとりあえずこんな感じでいいんじゃないでしょうか?
そもそもガシガシ書く場合、少なくともES6以上(or TypeScript)を使うはず。 こんな感じでよいかなと…。 化石のようなプロジェクトで対応する場合、この書き方が良いかと思われる。 関数も大体はオブジェクトリテラルで雑に定義しとけばだいたい事足りると思われる。 とか書いたらフロントエンドやってる人に怒られるかな…。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>
        <div id="test" style="width: 100px; height: 50px; background-color: gray;">
        </div>
        <script src="https://code.jquery.com/jquery-3.3.1.js"
          integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
          crossorigin="anonymous"></script>
        <script>
        jQuery.noConflict();
        (function($) {
          console.log('immediately invoked function start');
          var mainFunc = {
            bindMouseOver: function() {
              $('#test').bind("mouseover", function() {
                alert("onmouseover");
              });
            },
          };
          $(document).ready(function() {
            console.log('ready function start');
            mainFunc.bindMouseOver();
            console.log('ready function end');
          });
          console.log('immediately invoked function end');
        })(jQuery);
        </script>
    </body>
</html>

HTTP/1.1(+ブラウザの組み合わせ)だとリクエストが同時に6までしか飛ばなかったはずなので、 <script>がたくさん増えた場合、まぁ、仕方ないってあきらめるのがいいんでしょうね。 こういうプロジェクトの場合。 いや、webpackとかでbundleしろよってのもあるかもしれない。 うん、ここまで書いて、化石プロジェクトにつぎ足しするとき時間があればwebpack+TypeScriptでいい、という結論になりそう(;^ω^)。いやでもめんどくさい…

HTTP/1.1について

Apache + Spring Bootの環境構築メモ

f:id:fa11enprince:20180508140318j:plain 開発環境での構築手順です。 本番環境ならajpを使ったほうが良いと思います。
組込みTomcat(jar)を使った場合のajpの有効化方法は後述します。
今回は単純にApacheとSpring Bootをhttpで連携する方法を書きます。
Windowsを想定しています。
(Linuxとほぼ変わらないですが、
今回使うApcheのディストリビューションの形式がLinuxの一般的なものと配置などが違っています。)

Spring Bootのjarの準備

単純にmvn install / mvn packageなどすればjarが出来上がります(Mavenの場合)。

Apacheのインストール

入手先がわかりにくいので、
https://httpd.apache.org/download.cgi
Files for Microsoft Windowsのリンクをたどる
https://httpd.apache.org/docs/current/platform/windows.html#down
に飛ぶはずなので、Apache Loungeのリンクを押します。
そうすると、
https://www.apachelounge.com/download/
に飛びますので、 Apache 2.4.38 Win64
をダウンロードします

ダウンロードしたhttpd-2.4.38-win64-VC15.zipを展開します。

httpd-2.4.38-win64-VC15フォルダの中に

Apache24フォルダ
-- Win64 VC15  --
ReadMe.txt

があるので、ReadMe.txtを_ReadMe.txtにリネームしてApache24フォルダに移動させましょう。
リネームしたReadMe.txtは大事なことが書いてあるので一度読んでおきましょう。
-- Win64 VC15 --はどうでもいいのですが、これも一応移動させておきましょう。
あとはApache24フォルダをCドライブ直下に置けばOKです。

Apacheの設定とサービス化

最低限の設定をします。 今回は単純にhttp://localhost:8080をリバースプロクシするだけということにしておきます。

Apache24\conf\httpd.conf

なにやらいっぱいモジュールの設定がコメントアウトされていますが、

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

の2つを有効化するだけでOKです(今回はajpを使いませんが)。
今回DocumentRootの設定は特にいじりません。
htdocsが嫌とかそういうことがあれば変えてください。 Options Indexes FollowSymLinksとかAllowOverride Noneとかなんだっけという方はこちら。
core - Apache HTTP サーバ バージョン 2.4

あと、末尾にTimeOut 3600を付け加えておきます

Apache24\conf\extra\proxy-html.conf

末尾に追加します

# /images/... へのリクエストはプロキシしない(必要に応じて)
ProxyPass /images/ ! 

ProxyPass        / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/

2行目はWebアプリ内部で/imagesでアクセスできるものがあればプロクシしたくないはずなので、 たいていは書くことになるのかなと思います。 具体的にはSpring Boot配下に作ったstatic/imagespublic/imagesが存在するときです。

これらが終われば、管理者でコマンドプロンプトを立ち上げて

C:\Apache24\bin\httpd -t

と打ってSyntax OKとでればサービス化します

C:\Apache24\bin\httpd -k install

でおしまいです。サービス一覧で確認すると起動していると思います。

組込みTomcatでのajp有効化方法

java - Spring Boot 2 - AJP - Stack Overflow によると下記のように書くとできるそうです。 Spring Boot 2ではこのように書きます。

import org.apache.catalina.connector.Connector;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import java.util.Optional;
 
@Configuration
public class AppConfig {
 
    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainer() {
        return server ->
            Optional.ofNullable(server)
                    .ifPresent(s -> s.addAdditionalTomcatConnectors(redirectConnector()));
    }
 
    private Connector redirectConnector() {
        Connector connector = new Connector("AJP/1.3");
        connector.setScheme("http");
        connector.setPort(8009);
        connector.setRedirectPort(8443);
        connector.setSecure(false);
        connector.setAllowTrace(false);
        return connector;
    }
}

この場合設定ファイルを

ProxyPass        / ajp://localhost:8009/
ProxyPassReverse / ajp://localhost:8009/

とするだけです。 検証したら追記・修正するかも…。

そもそもAJPとは

ざっくりいうとAJPのほうが早いらしくHTTPのようなオーバヘッドがない。
Apache HTTP ServerとTomcat間をバイナリでやり取りするとのこと。

Spring Boot 例外処理/エラーハンドリングメモ

f:id:fa11enprince:20190306032659j:plain

Spring Bootでは例外処理はthrowしてしまえばわりとよしなにやってくれるが… それでも考えるべきことはある。 場合によっては例外処理をあまり使わず、オブジェクトの戻り値による処理をすることもある。 と、去年の1月からSpring Bootを使い始めてSpringの良さがわかり、Springの深いところに潜り始めた。 気になったところをメモします。 気が向いたら更新しようかと思います。 雑にメモしていたので、気づいた誤りを修正しました。

全てここを参考にさせていただいています。 いろいろ学びが多く、とても良い資料です。

例外処理のパターン@Controller編

基本的には

  1. @Controllerに個別で@ExceptionHandler
  2. @ControllerAdvice@ExceptionHandler
  3. Spring BootのError Controller

3番目は知らなかった 1番目と2番目はよく使うと思う

@Slf4j
@ControllerAdvice("com.example.controllers.foo")
public class GlobalControllerAdvice {
    @ExceptionHandler(Exception.class)
    public String handleException(Exception e, HttpServletResponse response, Model model) {
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        log.error("Error occurred.", e);
        model.addAttribute("errorMessage", e.getMessage());
        
        return "foo/error";
    }
}

プレゼンテーション層、404エラーなど全ての例外を補足できない&status codeがセットされないという問題がある

ErrorControllerを使う

Spring MVCでは次の順に呼ばれるとのこと

  1. ExceptionHandlerExceptionResolver(@ExceptionHandler)
  2. ResponseStatusExceptionResolver(@ResponseStatus)
  3. DefaultHandlerExceptionResolver(Spring MVCで起きた例外を処理)

ErrorControllerはこれらが適用された後に呼ばれる

例外処理のパターン@RestController編

  1. @RestControllerに個別で@ExceptionHandler
  2. @RestControllerAdvice@ExceptionHandler
  3. @ResponseStatusを付与した例外をThrow

ExceptionHandlerを使う場合

@Data
public class ErrorResponse {
    private String keyName;
    private String keyValue;
    private String message;

    public ErrorResponse(String keyName, String keyValue, String message) {
        this.keyName = keyName;
        this.keyValue = keyValue;
        this.message = message;
    }
    public ResponseEntity<ErrorResponse> createResponse(HttpStatus status) {
        return new ResponseEntity<ErrorResponse>(this, status);
    }
    public static ResponseEntity<ErrorResponse> createResponse(BadRequestException e) {
        return new ResponseEntity<ErrorResponse>(
                new ErrorResponse(e.getKeyName(), e.getKeyValue(), e.getMessage())
                    ,HttpStatus.BAD_REQUEST);
    }
}

自前例外(CreateResponseの引数になる)

@Data
public class BadRequestException extends Exception {

    private String keyName;
    private String keyValue;
    private String message;

    public BadRequestException(String keyName, String keyValue, String message) {
        this.keyName = keyName;
        this.keyValue = keyValue;
        this.message= message;
    }

}

例外ハンドラ

@RestControllerAdvice
public class BadRequestExceptionHandler {

    @ExceptionHandler(BadRequestException.class)
    public ResponseEntity<ErrorResponse> getException(HttpServletRequest req, BadRequestException e) {
        return ErrorResponse.createResponse(e);
    }
    
}

なお、 SpringBootの@RestControllerで例外処理をする - Qiita によると、 既に用意してあるhandlerを継承したほうが良いかもしれない。

@RestControllerAdvice
public class BazExceptionHandler extends ResponseEntityExceptionHandler {

    // 自分で定義したMyExceptionをキャッチする
    @ExceptionHandler(MyException.class)
    public ResponseEntity<?> handleMyException(MyException ex, WebRequest request) {
        return super.handleExceptionInternal(ex, "handleMyException", null, HttpStatus.BAD_REQUEST, request);
    }
...snip...

ちなみにですが、 ResponseEntity<?>ResponseEntity<Object>ResponseEntity<? extends Object>とだいたい一緒です。。 つまり何らかのクラスってことです。 細かいことは境界ワイルドカード型(bounded wildcard type)で調べるとわかるかと思います。 Springつかうとこれじゃないと返せないケースがあります。

その他リンク

https://www.baeldung.com/exception-handling-for-rest-with-spring https://www.slideshare.net/shintanimoto/spring-boot10 https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html