使用 `jetty` 启动器 或者 `undertow` 启动器可以开发 jsp 项目（jsp 只能做为视图使用）。方案有二：

* 方案1：
  * solon-web
  * solon-server-undertow
  * solon-server-undertow-add-jsp
  * solon-view-jsp
* 方案2：
  * solon-web
  * solon-server-jetty
  * solon-server-jetty-add-jsp
  * solon-view-jsp



此文用“方案1”进行系统演示，且不显示使用 Servlet 对象：

### 1、 开始Meven配置走起

```xml
    <parent>
        <groupId>org.noear</groupId>
        <artifactId>solon-parent</artifactId>
        <version>3.10.1</version>
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>org.noear</groupId>
            <artifactId>solon-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.noear</groupId>
            <artifactId>solon-server-undertow</artifactId>
        </dependency>

        <dependency>
            <groupId>org.noear</groupId>
            <artifactId>solon-server-undertow-add-jsp</artifactId>
        </dependency>

        <dependency>
            <groupId>org.noear</groupId>
            <artifactId>solon-view-jsp</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>
```

### 2、 其它代码和平常开发就差不多了

```xml
//资源路径约定（不用配置；也不能配置）
resources/app.yml（ 或 app.properties ） #为应用配置文件

resources/static/      #为静态文件根目录（v2.2.10 后支持）
resources/templates/   #为视图模板文件根目录（v2.2.10 后支持）

//调试模式约定：
启动参数添加：--debug=1
```

* 添加个控制器 `src/main/java/webapp/controller/HelloworldController.java`

```java
@Controller
public class HelloworldController {

    //这里注入个配置
    @Inject("${custom.user}")
    protected String user;

    @Mapping("/helloworld")
    public ModelAndView helloworld(Context ctx){
        UserModel m = new UserModel();
        m.setId(10);
        m.setName("刘之西东");
        m.setSex(1);

        ModelAndView vm = new ModelAndView("helloworld.jsp"); //如果是ftl模板，把后缀改为：.ftl 即可

        vm.put("title","demo");
        vm.put("message","hello world!");

        vm.put("m",m);

        vm.put("user", user);

        vm.put("ctx",ctx);

        return vm;
    }
}
```

* 再搞个自定义标签 `src/main/java/webapp/widget/FooterTag.java` （对jsp来说，这个演示很重要）

```java
public class FooterTag extends TagSupport {
    @Override
    public int doStartTag() throws JspException {
        try {
            String path = Context.current().path();

            //当前视图path
            StringBuffer sb = new StringBuffer();
            sb.append("<footer>");
            sb.append("我是自定义标签，FooterTag；当前path=").append(path);
            sb.append("</footer>");
            pageContext.getOut().write(sb.toString());
        }
        catch (Exception e){
            e.printStackTrace();
        }

        return super.doStartTag();
    }

    @Override
    public int doEndTag() throws JspException {
        return super.doEndTag();
    }
}
```

* 加tld描述文件 `src/main/resources/WEB-INF/tags.tld` （位置别乱改，就放这儿...）

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">

    <description>自定义标签库</description>
    <tlib-version>1.1</tlib-version>
    <short-name>ct</short-name>
    <uri>/tags</uri>

    <tag>
        <name>footer</name>
        <tag-class>webapp.widget.FooterTag</tag-class>
        <body-content>empty</body-content>
    </tag>

</taglib>
```

* 视图 `src/main/resources/WEB-INF/view/helloworld.jsp`

```html
<%@ page import="java.util.Random" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="ct" uri="/tags" %>
<html>
<head>
    <title>${title}</title>
</head>
<body>
<div>
    context path: ${ctx.path()}
</div>
<div>
    properties: custom.user :${user}
</div>
<main>
    ${m.name} : ${message} （我想<a href="/jinjin.htm">静静</a>）
</main>
<ct:footer/>
</body>
</html>
```

### 3、 疑问

一路上没有web.xml ? 是的，没有。

### 4、 源码

[https://gitee.com/noear/solon-examples/tree/main/3.Solon-Web/demo3013-web_jsp](https://gitee.com/noear/solon-examples/tree/main/3.Solon-Web/demo3013-web_jsp)
