# [Java] Apunts d'estudi de JSP i Servlet

> JSP i Servlet. Els vídeos que acompanyen aquests apunts són 《【Tutorial en vídeo de JavaEE de SiKi学院】JavaWeb Primera temporada: bàsic》 《【Tutorial en vídeo de JavaEE de SiKi学院】JavaWeb Segona temporada: avançat》. Prefaci: Segons la meva comprensió, JSP està a prop de la jubilació; no cal aprofundir-hi, n'hi ha prou amb una aproximació. En canvi, Servlet requereix una comprensió profunda, ja que és…

- Publicat el: 2019-11-16
- Etiquetes: Java, Servlet
- Veure versió HTML: https://bilibili.cat/ca/posts/java-jsp-servlet
- Traduït per IA des de 中文: https://bilibili.cat/posts/java-jsp-servlet

---

# JSP i Servlet

> #### Els vídeos que acompanyen aquests apunts són
>
> > [《【Tutorial en vídeo de JavaEE de SiKi学院】JavaWeb Primera temporada: bàsic》](http://www.sikiedu.com/course/214)  
> > [《【Tutorial en vídeo de JavaEE de SiKi学院】JavaWeb Segona temporada: avançat》](http://www.sikiedu.com/course/218)

> #### Prefaci
>
> > Segons la meva comprensió, JSP està a prop de la jubilació; no cal aprofundir-hi, n'hi ha prou amb una aproximació.  
> > En canvi, Servlet requereix una comprensió profunda, ja que és la base de molts frameworks en el futur.

## ***Conté codi de diagrames de flux; es recomana consultar-lo amb un editor Markdown professional (Evernote també serveix).***

---

## Sintaxi bàsica de JSP

#### Importació

```jsp
<%@page import=""%>
```

#### Comentaris

```jsp
<%-- code --%>
```

#### Escriptura

```jsp
<% code %>
```

#### Definició d'expressions

```jsp
<%! 成员变量 %>
```

#### Inclusió d'etiquetes

> En general, es pot utilitzar per importar contingut repetit de diverses pàgines web
>
> o

```xml
<jsp:include page="xxx.jsp"></jsp:include>
```

## Classes internes i els seus mètodes habituals

> #### out (== sou)
>
> > println()  
> > S'utilitza println() per a la sortida; també es pot substituir per “=”
>
> #### request (el cicle de vida només dura una petició HTTP)
>
> > 1.  getParameter()  
> >     Obté paràmetres
> > 2.  getRequestDispatcher(url).forward(request, response)  
> >     Reenviament de petició request\_do->login->client (cal parar atenció als problemes de rutes)
> > 3.  setAttribute(key, content)/getAttribute(key)  
> >     Passa valors
> > 4.  getSession()  
> >     Obté l'objecte session
> > 5.  getContextPath()  
> >     Obté la ruta del projecte; s'utilitza per a rutes relatives
>
> #### response
>
> > 1.  getWriter().println()  
> >     S'escriu a la capçalera HTML
> > 2.  getWriter().append()  
> >     Afegeix
> > 3.  sendRedirect(url)  
> >     Redirecció request\_do->client->login
>
> #### session
>
> > setAttribute(key, content)/getAttribute(key)  
> > Passa valors
>
> #### application (objecte únic)
>
> > setAttribute(key, content)/getAttribute(key)  
> > Passa valors
>
> #### page
>
> > \== la paraula clau this
>
> #### pageContext (contenidor)
>
> > 1.  getOut()  
> >     Obté l'objecte out
> > 2.  getRequest()  
> >     req
> > 3.  getResponse()  
> >     resp
> > 4.  getServletContext()  
> >     app
> > 5.  getSession()  
> >     session

## Servlet

> Només s'encarrega del processament del flux, separat de JSP.  
> extend HttpServlet throw ~Exception  
> S'utilitza reescrivint doGet(req, resp) i doPost(req, resp)
>
> Es localitza amb l'anotació @WebServlet(“url”)  
> També es pot localitzar amb web.xml (en crear el projecte, marcant next es pot crear automàticament)

```xml
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>
com.sikiedu.servlet.LoginServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login_ do</url-pattern><!-- 访问路径-->
</servlet-mapping>
</servlet>
```

---

> #### Cicle de vida

![Diagrama de flux 1](https://cos2.endcloud.cn/legacy/halo/java-jsp-servlet/mermaid-1.svg)

## Expressions EL

> Serveixen per simplificar l'escriptura de JSP, reduir la quantitat de codi i millorar la llegibilitat.

#### Obtenció de variables

> 1.  $
> 2.  $
>
> (~ és req, session, application)  
> (la prioritat de l'àmbit és req, session, application)
>
> ***Normalment n'hi ha prou amb la primera forma***

#### Obtenció de variables de classe

> $

#### Obtenció de map i col·leccions

> ${map.key} i $

#### Operacions

> ${±\*/}  
> ${> \< == || !}  
> $

#### Classes internes

> $

## Etiquetes JSTL

> Simplifiquen encara més l'escriptura de JSP i milloren la llegibilitat del codi.  
> Tenen un embrió de sintaxi dels frameworks front-end moderns basats en dades.  
> Com Vue.js i Angular.js.

#### Descarregar el paquet JAR

> [Enllaç de descàrrega -> mvnrepository](https://mvnrepository.com/artifact/javax.servlet/jstl/1.2)

#### Importació

```xml
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
```

#### Definició de valors

```xml
<c:set var="" value="" scope=""></c:set>
```

#### Eliminació de valors

```xml
<c:remove var=""/>
```

#### Sortida de valors

```xml
<c:out value=""/>
```

#### Condició

```xml
<c:choose>
<c:when test="${condition}">code</c:when>
<c:otherwise>code</c:otherwise>
</c:choose>
```

#### Bucle

```xml
<c:foreach var="i" begin="index1" end="index2">
code
</c:foreach>
<c:foreach items="${list}" var="x">${x.var}</c:foreach>
```

## JSON

> El nom complet és "JavaScript Object Notation";  
> és un format lleuger d'intercanvi de dades; el seu prototip és l'objecte de dades de JavaScript.  
> [Més informació](https://www.json.org/json-zh.html)

## fastjson

> Biblioteca de codi obert per a operar amb JSON en Java, creada per Alibaba.  
> [GitHub oficial de fastjson](https://github.com/alibaba/fastjson)

#### Descarregar el paquet JAR

> [Enllaç de descàrrega->mvnrepository](https://mvnrepository.com/artifact/com.alibaba/fastjson/1.2.62)

#### Importació

```java
import com.alibaba.fastjson.JSON
```

#### Serialització

```java
JSON.toJSONString(object);
```

#### Deserialització

```java
JSON.parseObject(String, object.class);
```

#### Serialització d'arrays

```java
JSON.parseArray(String, object.class);
```

## AJAX

> El nom complet és "Asynchronous Javascript And XML";  
> és una tècnica que, mitjançant peticions asíncrones, permet actualitzar dades sense recarregar la pàgina web.  
> ***Aquesta és una tecnologia de JavaScript, no de Java.***

#### Implementació amb JQuery

```JavaScript
setInterval("callAjax()", 2000);//定时调用方法，参数单位为毫秒
function callAjax() {
    $.ajax({
        url: "${pageContext.request.contextPath }/ajaxrequest" ,
        type:"get",
        success: function(msg){
            }
});
$("input").blur(callAjax); //失焦响应方法
```

#### Implementació amb JS natiu

```JavaScript
function callAjaxByJS(){
    var xmlhttp = new XMLHttpRequest();
    xmlhttpopen("GET", endcodeURI("${pageContext.request.contextPath}/ajaxRequest?data=我是数据&"+Math.random()), true)
    xmlhttp.send();
    xmlhttp.onreadystatechange = function(){
    if( xmlhttp.readyState==4 && xmlhttp.status==200 ){
     //得到了服务器端的响应，4代表ajax响应已完成，200是http正常状态码
            $("#msg").append(xmlhttp.responseText);
        }
    }
}
```

## Filter

> class implement Filter

#### Cicle de vida

> Constructor->init()->doFilter()->destory()

#### doFilter()

> chain.doFilter() inicia la cadena de filtres.

```java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{
    // TODO Auto-generated method stub
    // place your code here
    System.out.println("test1 filter before");
    // pass the request along the filter chain
    chain.doFilter(request, response);
    System.out.println("test1 filter after");
}
```

> Es poden configurar les condicions i l'ordre dels filtres mitjançant web.xml;  
> també es poden establir condicions amb @WebFilter(“/\*”).

```xml
<filter>
<filter-name>Test1Filter</filter-name><!-- 名称 -->
<filter-class>com.sikiedu.filter.Test1Filter</filter-class><!-- 类名 -->
</filter>
<filter>
<filter-name>Test2Filter</filter-name>
<filter-class>com. sikiedu.filter.Test2Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>Test2Filter</filter-name>
<url-pattern>/*</url-pattern><!-- 过滤目录 -->
</filter-mapping>
<filter-mapping>
<filter-name>Test1Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
```

> L'ordre establert a web.xml s'inverteix en la resposta,  
> és a dir, s'executa el codi escrit després de chain.doFilter().  
> Normalment no cal utilitzar-ho.

#### Filtratge de gestió de permisos

```xml
<filter>
<filter-name>AdminFilter</filter -name>
<filter-class>com.sikiedu.filter.AdminFilter</filter-class>
<!-- 继承自Filter的类-->
</filter>
<filter-mapping>
<filter-name>AdminFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
<!-- 此处为路径，*是通配符，代表所有 -->
</filter-mapping>
```

#### Filtratge de peticions

> Filtra el tipus de petició que el client adreça a JSP.  
> ***Aquesta petició no es refereix a GET i POST, sinó al tipus de petició definit per JSP.***

```xml
<filter>
<filter-name>DispatcherFilter</filter-name>
<filter-class>com.sikiedu.filter.DispatcherFilter</filter-class><!-- 继承自Filter的类-->
</filter>
<filter-mapping>
<filter-name>DispatcherFilter</filter-name>
<url-pattern>/dispatcher1. jsp</url-pattern>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
```

> Hi ha cinc tipus de dispatcher; els quatre primers són els habituals.
>
> > 1.  REQUEST Petició normal
> > 2.  FORWARD Reenviament de petició
> > 3.  INCLUDE \<jsp:include>
> > 4.  ERROR Petició d'error
> > 5.  ASYNC Petició asíncrona???
> >
> > #### Configuració de pàgines d'error

```xml
<error-page>
<error-code>404</error-code>
<location>/dispatcher1.jsp</location>
</error-page>
```

## Listeners

> 1.  Un listener és una classe; creeu la classe
> 2.  Implementeu la interfície de listener
>
> > Monitoratge de l'estat de creació i destrucció  
> > ~initialized() ~Destroyed()
> >
> > > javax.servlet.ServletContextListener  
> > > HttpSessionListener  
> > > ServletRequestListener
> >
> > Monitoratge d'atributs  
> > ~Added() ~Replaced() ~Removed()
> >
> > > ServletContextAttributeListener  
> > > HttpSessionAttributeListener  
> > > ServletRequestAttributeListener
> >
> > Monitoratge de vinculació de sessió
> >
> > > 1.  Feu que el model implementi HttpSessionBindingListener
> > > 2.  Reescriu els mètodes valueBound() i valueunbound()

> 3.  Configuració

```xml
<listener>
<listener-class>package.Listen-name.class</listener-class>
</listener>
```

> 4.  Establir el temps d'expiració de la sessió

```xml
<session-contig>
<session-timeout>1</session-timeout><!-- 单位为分钟-->
</session-config>
```

# Conceptes especials

## Arquitectura MVC

![Diagrama de flux 2](https://cos2.endcloud.cn/legacy/halo/java-jsp-servlet/mermaid-2.svg)

## Arquitectura per capes J2EE

![Diagrama de flux 3](https://cos2.endcloud.cn/legacy/halo/java-jsp-servlet/mermaid-3.svg)

## Patró Singleton

> Privatitzeu el constructor i creeu una instància.  
> Eviteu fer new diverses vegades sobre objectes d'ús habitual.

```java
public static JDBCUtil instance = new JDBCUtil();
private JDBCUtil() {

}
```

## Rutes relatives i rutes absolutes

#### Rutes del client

> Es mostren a la barra d'adreces del client o al codi font i es poden sol·licitar.  
> Per exemple, [així com l'URL d'accés.](URL)

> Ruta relativa
>
> > Es determina per la ruta del directori de l'URL actual.
>
> Ruta absoluta
>
> > Es determina per la ruta arrel de l'amfitrió (domini).  
> > ***Normalment, s'hi afegeix contextPath per mantenir correcta la ruta.***  
> > <u>&lt;%=request.getContextPath()%&gt;</u>  
> > o <u>${pageContext.request.contextPath}</u>

#### Rutes del servidor

> Només s'executen dins de JSP.  
> Com \<jsp:include page=“xxx.jsp”> o el reenviament de petició.

> Ruta relativa
>
> > Es determina per la ruta on es troba el fitxer JSP actual, amb la forma "xxx.jsp".
>
> Ruta absoluta
>
> > Es determina per la ruta del projecte, amb la forma "/folder/xxx.jsp".  
> > ***No cal afegir-hi el nom del projecte.***

#### ***A l'ús real, es recomana utilitzar sempre <u>rutes absolutes</u> per evitar errors.***

## Solució dels problemes de caràcters corruptes en paràmetres xinesos

> Establir la codificació amb String

```java
System.out.println(new String(sex.getBytes("iso-8859-1"), "utf-8"));
```

> Establir la codificació a request

```java
request.setCharacterEncoding("utf-8");
```

> Establir la codificació a response

```java
resp.setContentType("text/html; charset=utf-8");
```

> ***Solució definitiva: establir la codificació globalment a doFilter***

```java
encoding = fConfig.getInitParameter("Encoding");
```

```xml
<!-- 在web.xml配置Encoding参数和filter-->
<filter>
<filter-name>EncodeFilter</filter-name>
<filter-class>com.sikiedu.filter.EncodeFilter</filter-class>
<init-param>
<param-name>Encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodeFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
```

## Inici de sessió únic

> 1.  Creeu la classe sessionManager i establiu una col·lecció de sessions (implementada amb hashmap).
> 2.  Controleu-ho mitjançant el listener added de session-attribute.

```java
if(arg0.getName().equals("user")) {
    User u = (User) arg0.getValue();
    //判断是否有其他客户端已经登录
    if(Sess ionManager . sess ionMppE containsKey(u. getUsername())) {
        //获得另外一一个客户端的session
        HttpSession session = SessionManager.sess ionMap. get(u.getUsername());
        //把登录信息从这个客户端抹除
        session. removeAttribute("user");
    }
    SessionManager.sessionMap.put(u.getUsername(), arg0.getSession());
}
```

## Epíleg

#### Propers passos d'aprenentatge

> Recomano orientar l'aprenentatge cap al framework SSM; siki学院 també té cursos.  
> El framework SSH està una mica desfasat en alguns aspectes; valoreu-ho segons el cas.

#### Si voleu buscar feina

> Recomano que, després d'haver entès el framework SSM, torneu a repassar els fonaments de Java.  
> Com a llibres de referència principals, els volums 1 i 2 de 《Java核心技术》.  
> Alhora, cal aprendre els coneixements bàsics relacionats amb estructures de dades i algorismes.

## Contacteu-me

#### GitHub

Si creieu que aquests apunts us poden ser d'alguna utilitat, us convido a donar-me una Star.  
Aquí teniu l'adreça del projecte d'aquests apunts: [GitHub](https://github.com/endcloud/JavaWeb_learn_siki)  
Més endavant, encara actualitzaré aquí el codi i els apunts relacionats.

Els meus coneixements encara són limitats; també podeu enviar-hi un PR per corregir els meus errors. Us ho agrairé molt.

#### e-mail

A més, també us podeu posar en contacte amb mi per correu electrònic.  
La meva adreça de correu és: endcloud@qq.com
