Strictly speaking this is not a web application framework as it is all custom code based on the basic building blocks of the technology.
But given that it is actually frequently used for MVC web applications, then it is relevant to cover.
Name and creator | N/A |
History | Servlet 1.0 was introduced in 1996 JSP 1.1 was introduced in 1999 JSTL 1.0 was introduced in 2002 |
Programming language | Java |
View technology | JSP |
Deployment | Servlet container |
Other technical characteristics | |
Status | All technologies involved are still actively maintained, but today it is probably only used for small projects - larger projects use a real framework |
We have a servlet controller that forward to the JSP view.
JSP is covered in detail in Java EE tricks.
test.jsp (view):
<%@ page language="java" %>
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Java (JSP + Servlet)</title>
</head>
<body>
<h1>Java (JSP + Servlet)</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<c:forEach items="${data}" var="o">
<tr>
<td><c:out value="${o.f1}"/></td>
<td><c:out value="${o.f2}"/></td>
<td><c:out value="${o.f3}"/></td>
</tr>
</c:forEach>
</table>
<h2>Add data:</h2>
<form method="post">
F1: <input type="text" name="f1">
<br>
F2: <input type="text" name="f2">
<br>
F3: <select name="f3">
<c:forEach items="${options}" var="opt">
<option><c:out value="${opt}"/></option>
</c:forEach>
</select>
<br>
<input type="submit" value="Add"/>
</form>
</body>
</html>
TestController.java (controller):
package demo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestController extends HttpServlet {
// options
private List<String> getOptions() {
List<String> res = new ArrayList<String>();
res.add("");
res.add(T1.VER);
res.add(T1.NOTVER);
return res;
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// get all data and save in request for use by JSP
request.setAttribute("data", DB.getAll());
// get options and save in request for JSP
request.setAttribute("options", getOptions());
// forward to JSP
request.getRequestDispatcher("test.jsp").forward(request, response);
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
// create object from form fields
T1 o = new T1(Integer.parseInt(request.getParameter("f1")), request.getParameter("f2"), request.getParameter("f3"));
// save object
DB.saveOne(o);
// redirect to GET
response.sendRedirect("startpage");
}
}
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
web.xml (configuration of web application):
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- define servlet -->
<servlet>
<servlet-name>TestController</servlet-name>
<servlet-class>demo.TestController</servlet-class>
</servlet>
<!-- map servlet to /startpage -->
<servlet-mapping>
<servlet-name>TestController</servlet-name>
<url-pattern>/startpage</url-pattern>
</servlet-mapping>
<!-- make /startpage default -->
<welcome-file-list>
<welcome-file>startpage</welcome-file>
</welcome-file-list>
</web-app>
Packaging of war file:
0 Fri Dec 02 10:11:34 EST 2022 META-INF/ 109 Fri Dec 02 10:11:32 EST 2022 META-INF/MANIFEST.MF 0 Fri Dec 02 10:11:34 EST 2022 WEB-INF/ 772 Wed Nov 23 20:16:04 EST 2022 WEB-INF/web.xml 0 Fri Dec 02 10:11:34 EST 2022 WEB-INF/classes/ 0 Fri Dec 02 10:11:32 EST 2022 WEB-INF/classes/demo/ 762 Fri Dec 02 10:11:32 EST 2022 WEB-INF/classes/demo/DB.class 746 Fri Dec 02 10:11:32 EST 2022 WEB-INF/classes/demo/T1.class 1540 Fri Dec 02 10:11:32 EST 2022 WEB-INF/classes/demo/TestController.class 831 Fri Nov 25 19:42:02 EST 2022 test.jsp
The result looks like:
Struts 1.x was the first widely used MVC web application framework and is helped promote MVC for web applications. So even though it is obsolete today, then it is still relevant for historic reasons.
Name and creator | Apache Struts 1.x / open source |
History | Version 1.0 in 2000 In 2005 it was decided to base Struts 2.x on WebWork instead of Struts 1.x |
Programming language | Java |
View technology | JSP |
Deployment | Servlet container |
Other technical characteristics | |
Status | Obsolete since Struts 2.x was released in 2007 |
In Struts 1.x a Struts controller servlet forward to a specific action class that forward to a JSP view.
JSP is covered in detail in Java EE tricks.
The JSP view can be done multiple ways. I will show:
Actions does not forward directly to views but to a logical name that get mapped to a view in Struts config.
test.jsp (view):
<%@ taglib uri="struts-html" prefix="html" %>
<%@ taglib uri="struts-logic" prefix="logic" %>
<%@ taglib uri="struts-bean" prefix="bean" %>
<html>
<head>
<title>Struts 1</title>
</head>
<body>
<h1>Struts 1</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<logic:iterate id="o" name="data">
<tr>
<td><bean:write name="o" property="f1"/></td>
<td><bean:write name="o" property="f2"/></td>
<td><bean:write name="o" property="f3"/></td>
</tr>
</logic:iterate>
</table>
<h2>Add data:</h2>
<html:form action="/add">
F1: <html:text property="f1"/>
<br/>
F2: <html:text property="f2"/>
<br/>
F3: <html:select property="f3">
<html:optionsCollection name="opt"/>
</html:select>
<br/>
<html:submit>Add</html:submit>
</html:form>
</body>
</html>
ListAction.java (action for list):
package demo;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
// list data action
public class ListAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
// get data and store in request
request.setAttribute("data", DB.getAll());
// get options and store in request
request.setAttribute("opt", Util.getOptions());
// forward to configured list.ok action
return mapping.findForward("list.ok");
}
}
AddAction.java (action for add):
package demo;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
// add data action
public class AddAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
// get form data
AddForm addfrm = (AddForm)form;
int f1 = Integer.parseInt(addfrm.getF1());
String f2 = addfrm.getF2();
String f3 = addfrm.getF3();
// store in database
DB.saveOne(new T1(f1, f2, f3));
// get data and store in request
request.setAttribute("data", DB.getAll());
// get options and store in request
request.setAttribute("opt", Util.getOptions());
// forward to configured add.ok action
return mapping.findForward("add.ok");
}
}
AddForm.java (form data for add):
package demo;
import org.apache.struts.action.ActionForm;
// form submit data
public class AddForm extends ActionForm {
private String f1;
private String f2;
private String f3;
public AddForm() {
this("", "", "");
}
public AddForm(String f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public String getF1() {
return f1;
}
public void setF1(String f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
Util.java (option list):
package demo;
import java.util.ArrayList;
import java.util.List;
public class Util {
public static class Option {
private String label;
private String value;
public Option() {
this("", "");
}
public Option(String label, String value) {
this.label = label;
this.value = value;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
// option list
public static List<Option> getOptions() {
List<Option> res = new ArrayList<Option>();
res.add(new Option("", ""));
res.add(new Option(T1.VER, T1.VER));
res.add(new Option(T1.NOTVER, T1.NOTVER));
return res;
}
}
web.xml (configuration of web application):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- define Struts servlet -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>5</load-on-startup>
</servlet>
<!-- map *.do to Struts servlet -->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- make /list.do default -->
<welcome-file-list>
<welcome-file>list.do</welcome-file>
</welcome-file-list>
<!-- Strust taglibs -->
<taglib>
<taglib-uri>struts-html</taglib-uri>
<taglib-location>/WEB-INF/lib/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>struts-bean</taglib-uri>
<taglib-location>/WEB-INF/lib/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>struts-logic</taglib-uri>
<taglib-location>/WEB-INF/lib/struts-logic.tld</taglib-location>
</taglib>
</web-app>
struts-config.xml (configuration of Struts):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd" >
<struts-config>
<form-beans>
<form-bean name="addForm" type="demo.AddForm"/>
</form-beans>
<action-mappings>
<action path="/list" type="demo.ListAction">
<forward name="list.ok" path="/test.jsp"/>
</action>
<action path="/add" type="demo.AddAction" name="addForm" input="/test.jsp">
<forward name="add.ok" path="/test.jsp"/>
</action>
</action-mappings>
<message-resources parameter="messages.appResources" null="true"/>
</struts-config>
Packaging of war file:
0 Fri Dec 02 10:38:34 EST 2022 META-INF/ 109 Fri Dec 02 10:38:32 EST 2022 META-INF/MANIFEST.MF 0 Fri Dec 02 10:38:34 EST 2022 WEB-INF/ 1370 Wed Nov 23 20:25:00 EST 2022 WEB-INF/web.xml 0 Fri Dec 02 10:38:34 EST 2022 WEB-INF/classes/ 0 Fri Dec 02 10:38:34 EST 2022 WEB-INF/classes/demo/ 1169 Fri Dec 02 10:38:34 EST 2022 WEB-INF/classes/demo/AddAction.class 648 Fri Dec 02 10:38:34 EST 2022 WEB-INF/classes/demo/AddForm.class 762 Fri Dec 02 10:38:34 EST 2022 WEB-INF/classes/demo/DB.class 861 Fri Dec 02 10:38:34 EST 2022 WEB-INF/classes/demo/ListAction.class 746 Fri Dec 02 10:38:34 EST 2022 WEB-INF/classes/demo/T1.class 598 Fri Dec 02 10:38:34 EST 2022 WEB-INF/classes/demo/Util$Option.class 588 Fri Dec 02 10:38:34 EST 2022 WEB-INF/classes/demo/Util.class 812 Wed Nov 23 20:26:28 EST 2022 test.jsp 0 Fri Dec 02 10:38:34 EST 2022 WEB-INF/lib/ 8868 Sun Jun 29 16:50:08 EDT 2003 WEB-INF/lib/struts-bean.tld 66192 Sun Jun 29 16:50:14 EDT 2003 WEB-INF/lib/struts-html.tld 14511 Sun Jun 29 16:50:06 EDT 2003 WEB-INF/lib/struts-logic.tld 498051 Sun Jun 29 16:50:00 EDT 2003 WEB-INF/lib/struts.jar 721 Wed Nov 23 20:25:16 EST 2022 WEB-INF/struts-config.xml
The result looks like:
test.jsp (view):
<%@ page language="java" %>
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Struts 1 with JSTL and DynaForm</title>
</head>
<body>
<f:view>
<h1>Struts 1 with JSTL and DynaForm</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<c:forEach items="${data}" var="o">
<tr>
<td><c:out value="${o.f1}"/></td>
<td><c:out value="${o.f2}"/></td>
<td><c:out value="${o.f3}"/></td>
</tr>
</c:forEach>
</table>
<h2>Add data:</h2>
<form method="post" action="add.do">
F1: <input type="text" name="f1">
<br>
F2: <input type="text" name="f2">
<br>
F3: <select name="f3">
<c:forEach items="${options}" var="opt">
<option><c:out value="${opt}"/></option>
</c:forEach>
</select>
<br>
<input type="submit" value="Add"/>
<form>
</body>
</html>
ListAction.java (action for list):
package demo;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
// list data action
public class ListAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
// get data and store in request
request.setAttribute("data", DB.getAll());
// get options and store in request
request.setAttribute("options", Util.getOptions());
// forward to configured list.ok action
return mapping.findForward("list.ok");
}
}
AddAction.java (action for add):
package demo;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;
// add data action
public class AddAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
// get form data
DynaActionForm daf = (DynaActionForm)form;
int f1 = Integer.parseInt((String)daf.get("f1"));
String f2 = (String)daf.get("f2");
String f3 = (String)daf.get("f3");
// store in database
DB.saveOne(new T1(f1, f2, f3));
// get data and store in request
request.setAttribute("data", DB.getAll());;
// get options and store in request
request.setAttribute("options", Util.getOptions());;
// forward to configured add.ok action
return mapping.findForward("add.ok");
}
}
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
Util.java:
package demo;
import java.util.ArrayList;
import java.util.List;
public class Util {
// option list
public static List<String> getOptions() {
List<String> res = new ArrayList<String>();
res.add("");
res.add(T1.VER);
res.add(T1.NOTVER);
return res;
}
}
web.xml (configuration of web application):
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- define Struts servlet -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>5</load-on-startup>
</servlet>
<!-- map *.do to Struts servlet -->
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- make /list.do default -->
<welcome-file-list>
<welcome-file>list.do</welcome-file>
</welcome-file-list>
</web-app>
struts-config.xml (configuration of Struts):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd" >
<struts-config>
<form-beans>
<form-bean name="addForm" type="org.apache.struts.action.DynaActionForm">
<form-property name="f1" type="java.lang.String"/>
<form-property name="f2" type="java.lang.String"/>
<form-property name="f3" type="java.lang.String"/>
</form-bean>
</form-beans>
<action-mappings>
<action path="/list" type="demo.ListAction">
<forward name="list.ok" path="/test.jsp"/>
</action>
<action path="/add" type="demo.AddAction" name="addForm" input="/test.jsp">
<forward name="add.ok" path="/test.jsp"/>
</action>
</action-mappings>
<message-resources parameter="messages.appResources" null="true"/>
</struts-config>
Packaging of war file:
0 Fri Dec 02 10:49:16 EST 2022 META-INF/ 109 Fri Dec 02 10:49:14 EST 2022 META-INF/MANIFEST.MF 0 Fri Dec 02 10:49:16 EST 2022 WEB-INF/ 974 Wed Nov 23 21:19:44 EST 2022 WEB-INF/web.xml 0 Fri Dec 02 10:49:16 EST 2022 WEB-INF/classes/ 0 Fri Dec 02 10:49:16 EST 2022 WEB-INF/classes/demo/ 1241 Fri Dec 02 10:49:16 EST 2022 WEB-INF/classes/demo/AddAction.class 762 Fri Dec 02 10:49:16 EST 2022 WEB-INF/classes/demo/DB.class 865 Fri Dec 02 10:49:16 EST 2022 WEB-INF/classes/demo/ListAction.class 746 Fri Dec 02 10:49:16 EST 2022 WEB-INF/classes/demo/T1.class 423 Fri Dec 02 10:49:16 EST 2022 WEB-INF/classes/demo/Util.class 878 Wed Nov 23 21:20:12 EST 2022 test.jsp 0 Fri Dec 02 10:49:16 EST 2022 WEB-INF/lib/ 231320 Wed Nov 23 21:04:00 EST 2022 WEB-INF/lib/commons-beanutils-1.8.0.jar 91699 Wed Nov 23 21:04:00 EST 2022 WEB-INF/lib/commons-chain-1.2.jar 329441 Wed Nov 23 21:04:00 EST 2022 WEB-INF/lib/struts-core-1.3.10.jar 957 Wed Nov 23 20:44:02 EST 2022 WEB-INF/struts-config.xml
The result looks like:
Struts 2.x is based on WebWork not on Struts 1.x and even though it was a clear improvement then it never became as popular as Struts 1.x and the users moved to Spring MVC and JSF.
Name and creator | Apache Struts 2.x / open source |
History | WebWork version 1.1 in 2002 Struts version 2.0 in 2007 |
Programming language | Java |
View technology | JSP |
Deployment | Servlet container |
Other technical characteristics | |
Status | Actively maintained, but not widely used |
In Struts 2.x a Struts controller servlet forward to a specific action class that forward to a JSP view (just like in Struts 1.x).
JSP is covered in detail in Java EE tricks.
test.jsp (view):
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Struts 2</title>
</head>
<body>
<h1>Struts 2</h1>
<h2>Show data (iterator):</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<s:iterator value="data">
<tr>
<td><s:property value="f1"/></td>
<td><s:property value="f2"/></td>
<td><s:property value="f3"/></td>
</tr>
</s:iterator>
</table>
<h2>Add data:</h2>
<s:form action="add">
<s:textfield name="f1" label="F1"/>
<s:textfield name="f2" label="F2"/>
<s:select name="f3" label="F3" list="options"/>
<s:submit value="Add"/>
</s:form>
</body>
</html>
ListAction.java (action for list):
package demo;
import java.util.ArrayList;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
public class ListAction extends ActionSupport {
// execute action
public String execute() {
// forward to configured list view
return "list";
}
// get data
public List<T1> getData() {
return DB.getAll();
}
// option list
public List<String> getOptions() {
List<String> res = new ArrayList<String>();
res.add("");
res.add(T1.VER);
res.add(T1.NOTVER);
return res;
}
}
AddAction.java (action for add):
package demo;
import com.opensymphony.xwork2.ActionSupport;
public class AddAction extends ActionSupport {
// form data
private String f1;
private String f2;
private String f3;
public String getF1() {
return f1;
}
public void setF1(String f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
// execute action
public String execute() {
// save
DB.saveOne(new T1(Integer.parseInt(f1), f2, f3));
// forward to configured list redirect
return "list";
}
}
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
web.xml (configuration of web application):
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
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-app_2_4.xsd">
<!-- define Struts 2 filter -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<!-- map everything to Struts 2 filter -->
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
struts.xml (configuration of Struts):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<package name="demo" extends="struts-default">
<default-action-ref name="list"/>
<action name="list" class="demo.ListAction" method="execute">
<result name="list">/test.jsp</result>
</action>
<action name="add" class="demo.AddAction" method="execute">
<result name="list" type="redirect"><param name="location">list.action</param></result>
</action>
</package>
</struts>
Packaging of war file:
0 Tue Dec 06 12:39:42 EST 2022 META-INF/ 109 Tue Dec 06 12:39:40 EST 2022 META-INF/MANIFEST.MF 0 Tue Dec 06 12:39:42 EST 2022 WEB-INF/ 652 Mon Dec 05 20:00:30 EST 2022 WEB-INF/web.xml 0 Tue Dec 06 12:39:42 EST 2022 WEB-INF/classes/ 0 Tue Dec 06 12:39:42 EST 2022 WEB-INF/classes/demo/ 780 Tue Dec 06 12:39:42 EST 2022 WEB-INF/classes/demo/AddAction.class 762 Tue Dec 06 12:39:42 EST 2022 WEB-INF/classes/demo/DB.class 634 Tue Dec 06 12:39:42 EST 2022 WEB-INF/classes/demo/ListAction.class 746 Tue Dec 06 12:39:42 EST 2022 WEB-INF/classes/demo/T1.class 614 Mon Dec 05 20:32:04 EST 2022 test.jsp 0 Tue Dec 06 12:39:42 EST 2022 WEB-INF/lib/ 72446 Mon Dec 05 15:19:48 EST 2022 WEB-INF/lib/commons-fileupload-1.4.jar 214788 Mon Dec 05 15:19:50 EST 2022 WEB-INF/lib/commons-io-2.6.jar 501879 Mon Dec 05 15:19:50 EST 2022 WEB-INF/lib/commons-lang3-3.8.1.jar 1524587 Mon Dec 05 15:19:56 EST 2022 WEB-INF/lib/freemarker-2.3.28.jar 750581 Mon Dec 05 15:19:56 EST 2022 WEB-INF/lib/javassist-3.20.0-GA.jar 276771 Mon Dec 05 15:19:56 EST 2022 WEB-INF/lib/log4j-api-2.12.1.jar 262229 Mon Dec 05 15:19:58 EST 2022 WEB-INF/lib/ognl-3.1.26.jar 1642030 Mon Dec 05 15:20:04 EST 2022 WEB-INF/lib/struts2-core-2.5.22.jar 681 Mon Dec 05 20:27:14 EST 2022 WEB-INF/classes/struts.xml
The result looks like:
Stripes is another framework intended to replace Struts 1.x. It was designed to be simple and easy to use.
Name and creator | Stripes / open source |
History | Version 1.0 in 2005 |
Programming language | Java |
View technology | JSP |
Deployment | Servlet container |
Other technical characteristics | |
Status | Development stopped in 2015 and it is de facto EOL |
In Stripes a Stripes controller servlet forward to a specific action class that forward to a JSP view.
JSP is covered in detail in Java EE tricks.
The actions can be mapped via *.action URL's or @UrlBinding annotations in Java code.
The JSP view can either be almost pure JSTL or use convenient Stripes tags.
list.jsp (view):
<%@ page language="java" %>
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld"%>
<html>
<head>
<title>Stripes</title>
</head>
<body>
<h1>Stripes</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<c:forEach items="${actionBean.data}" var="o">
<tr>
<td><c:out value="${o.f1}"/></td>
<td><c:out value="${o.f2}"/></td>
<td><c:out value="${o.f3}"/></td>
</tr>
</c:forEach>
</table>
<h2>Add data:</h2>
<form method="post" action='<stripes:url beanclass="demo.AddActionBean"/>'>
F1: <input type="text" name="f1">
<br>
F2: <input type="text" name="f2">
<br>
F3: <select name="f3">
<c:forEach items="${actionBean.options}" var="opt">
<option><c:out value="${opt}"/></option>
</c:forEach>
</select>
<br>
<input type="submit" value="Add"/>
</form>
</body>
</html>
ListActionBean.java (action for list):
package demo;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
public class ListActionBean implements ActionBean {
// boilerplate (best practice is to move to BaseActionBean class)
private ActionBeanContext ctx;
public void setContext(ActionBeanContext ctx){
this.ctx = ctx;
}
public ActionBeanContext getContext(){
return ctx;
}
// actual action
public ForwardResolution list() {
// forward to list.jsp
return new ForwardResolution("/list.jsp");
}
// get data
public List<T1> getData() {
return DB.getAll();
}
// option list
public List<String> getOptions() {
List<String> res = new ArrayList<String>();
res.add("");
res.add(T1.VER);
res.add(T1.NOTVER);
return res;
}
}
AddActionBean.java (action for add):
package demo;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
public class AddActionBean implements ActionBean {
// boilerplate (best practice is to move to BaseActionBean class)
private ActionBeanContext ctx;
public void setContext(ActionBeanContext ctx){
this.ctx = ctx;
}
public ActionBeanContext getContext(){
return ctx;
}
// form data
private String f1;
private String f2;
private String f3;
public String getF1() {
return f1;
}
public void setF1(String f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
// actual action
public RedirectResolution add() {
// save
DB.saveOne(new T1(Integer.parseInt(f1), f2, f3));
// redirect to list action
return new RedirectResolution(ListActionBean.class);
}
}
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
web.xml (configuration of web application):
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
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-app_2_4.xsd">
<!-- define Stripes filter and dispatcher servlet -->
<filter>
<filter-name>StripesFilter</filter-name>
<filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
<init-param>
<param-name>ActionResolver.Packages</param-name>
<param-value>demo</param-value>
</init-param>
</filter>
<servlet>
<servlet-name>StripesDispatcher</servlet-name>
<servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- map stripes filter and servlet -->
<filter-mapping>
<filter-name>StripesFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>StripesFilter</filter-name>
<servlet-name>StripesDispatcher</servlet-name>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<servlet-mapping>
<servlet-name>StripesDispatcher</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<!-- make /demo/List.action default -->
<welcome-file-list>
<welcome-file>demo/List.action</welcome-file>
</welcome-file-list>
</web-app>
Packaging of war file:
0 Tue May 23 19:45:12 EDT 2023 META-INF/ 109 Tue May 23 19:45:10 EDT 2023 META-INF/MANIFEST.MF 0 Tue May 23 19:45:12 EDT 2023 WEB-INF/ 1602 Tue May 23 13:22:58 EDT 2023 WEB-INF/web.xml 0 Tue May 23 19:45:12 EDT 2023 WEB-INF/classes/ 0 Tue May 23 19:45:12 EDT 2023 WEB-INF/classes/demo/ 1251 Tue May 23 19:45:12 EDT 2023 WEB-INF/classes/demo/AddActionBean.class 762 Tue May 23 19:45:12 EDT 2023 WEB-INF/classes/demo/DB.class 1072 Tue May 23 19:45:12 EDT 2023 WEB-INF/classes/demo/ListActionBean.class 746 Tue May 23 19:45:12 EDT 2023 WEB-INF/classes/demo/T1.class 960 Tue May 23 14:12:52 EDT 2023 list.jsp 0 Tue May 23 19:45:12 EDT 2023 WEB-INF/lib/ 4017 Tue Dec 06 12:59:00 EST 2022 WEB-INF/lib/StripesResources.properties 62050 Tue Dec 06 12:59:02 EST 2022 WEB-INF/lib/commons-logging-1.1.3.jar 56404 Tue Dec 06 12:59:02 EST 2022 WEB-INF/lib/cos-05Nov2002.jar 554674 Tue Dec 06 12:59:02 EST 2022 WEB-INF/lib/stripes-1.6.0.jar
The result looks like:
list.jsp (view):
<%@ page language="java" %>
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld"%>
<html>
<head>
<title>Stripes (stripes form)</title>
</head>
<body>
<h1>Stripes (stripes form)</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<c:forEach items="${actionBean.data}" var="o">
<tr>
<td><c:out value="${o.f1}"/></td>
<td><c:out value="${o.f2}"/></td>
<td><c:out value="${o.f3}"/></td>
</tr>
</c:forEach>
</table>
<h2>Add data:</h2>
<stripes:form beanclass="demo.AddActionBean">
F1: <stripes:text name="f1"/>
<br>
F2: <stripes:text name="f2"/>
<br>
F3: <stripes:select name="f3">
<stripes:options-collection collection="${actionBean.options}"/>
</stripes:select>
<br>
<stripes:submit name="add" value="Add"/>
</stripes:form>
</body>
</html>
ListActionBean.java (action for list):
package demo;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
@UrlBinding("/demo/list")
public class ListActionBean implements ActionBean {
// boilerplate (best practice is to move to BaseActionBean class)
private ActionBeanContext ctx;
public void setContext(ActionBeanContext ctx){
this.ctx = ctx;
}
public ActionBeanContext getContext(){
return ctx;
}
// actual action
public ForwardResolution list() {
// forward to list.jsp
return new ForwardResolution("/list.jsp");
}
// get data
public List<T1> getData() {
return DB.getAll();
}
// option list
public List<String> getOptions() {
List<String> res = new ArrayList<String>();
res.add("");
res.add(T1.VER);
res.add(T1.NOTVER);
return res;
}
}
AddActionBean.java (action for add):
package demo;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
@UrlBinding("/demo/add")
public class AddActionBean implements ActionBean {
// boilerplate (best practice is to move to BaseActionBean class)
private ActionBeanContext ctx;
public void setContext(ActionBeanContext ctx){
this.ctx = ctx;
}
public ActionBeanContext getContext(){
return ctx;
}
// form data
private String f1;
private String f2;
private String f3;
public String getF1() {
return f1;
}
public void setF1(String f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
// actual action
public RedirectResolution add() {
// save
DB.saveOne(new T1(Integer.parseInt(f1), f2, f3));
// redirect to list action
return new RedirectResolution(ListActionBean.class);
}
}
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
web.xml (configuration of web application):
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
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-app_2_4.xsd">
<!-- define Stripes filter and dispatcher servlet -->
<filter>
<filter-name>StripesFilter</filter-name>
<filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
<init-param>
<param-name>ActionResolver.Packages</param-name>
<param-value>demo</param-value>
</init-param>
</filter>
<servlet>
<servlet-name>StripesDispatcher</servlet-name>
<servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- map stripes filter and servlet -->
<filter-mapping>
<filter-name>StripesFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>StripesFilter</filter-name>
<servlet-name>StripesDispatcher</servlet-name>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<servlet-mapping>
<servlet-name>StripesDispatcher</servlet-name>
<url-pattern>/demo/*</url-pattern>
</servlet-mapping>
<!-- make demolist default -->
<welcome-file-list>
<welcome-file>demo/list</welcome-file>
</welcome-file-list>
</web-app>
Packaging of war file:
0 Tue May 23 19:50:52 EDT 2023 META-INF/ 109 Tue May 23 19:50:50 EDT 2023 META-INF/MANIFEST.MF 0 Tue May 23 19:50:52 EDT 2023 WEB-INF/ 1585 Tue May 23 14:27:44 EDT 2023 WEB-INF/web.xml 0 Tue May 23 19:50:52 EDT 2023 WEB-INF/classes/ 0 Tue May 23 19:50:52 EDT 2023 WEB-INF/classes/demo/ 1362 Tue May 23 19:50:52 EDT 2023 WEB-INF/classes/demo/AddActionBean.class 762 Tue May 23 19:50:52 EDT 2023 WEB-INF/classes/demo/DB.class 1184 Tue May 23 19:50:52 EDT 2023 WEB-INF/classes/demo/ListActionBean.class 746 Tue May 23 19:50:52 EDT 2023 WEB-INF/classes/demo/T1.class 0 Tue May 23 14:42:28 EDT 2023 WEB-INF/classes/StripesResources.properties 939 Tue May 23 19:50:44 EDT 2023 list.jsp 0 Tue May 23 19:50:52 EDT 2023 WEB-INF/lib/ 4017 Tue Dec 06 12:59:00 EST 2022 WEB-INF/lib/StripesResources.properties 62050 Tue Dec 06 12:59:02 EST 2022 WEB-INF/lib/commons-logging-1.1.3.jar 56404 Tue Dec 06 12:59:02 EST 2022 WEB-INF/lib/cos-05Nov2002.jar 554674 Tue Dec 06 12:59:02 EST 2022 WEB-INF/lib/stripes-1.6.0.jar
The result looks like:
Struts 2.x never became as popular as Struts 1.x - instead Spring MVC became the most widely used MVC web application framework.
Struts 2.x was not fully compatible with Struts 1.x and everybody was already using Spring for DI, so it made sense.
Spring MVC also supports RESTful web services, so it can be used for both traditional web applications and for HTML5 web applications.
Name and creator | Spring Framework MVC / open source |
History | Spring 1.0 was introduced in 2002 Spring Boot 1.0 was released in 2014 |
Programming language | Java |
View technology | JSP Thymeleaf |
Deployment | Servlet container Spring Boot |
Other technical characteristics | |
Status | Actively maintained |
The Spring front controller forward to the specific controller that forward to the view - JSP or Thymeleaf.
test.jsp (view):
<%@ page language="java" %>
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Spring with JSP</title>
</head>
<body>
<h1>Spring with JSP</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<c:forEach items="${data}" var="o">
<tr>
<td><c:out value="${o.f1}"/></td>
<td><c:out value="${o.f2}"/></td>
<td><c:out value="${o.f3}"/></td>
</tr>
</c:forEach>
</table>
<h2>Add data:</h2>
<form method="post">
F1: <input type="text" name="f1">
<br>
F2: <input type="text" name="f2">
<br>
F3: <select name="f3">
<c:forEach items="${options}" var="opt">
<option><c:out value="${opt}"/></option>
</c:forEach>
</select>
<br>
<input type="submit" value="Add"/>
</form>
</body>
</html>
TestController.java (controller):
package demo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class TestController {
// options
private List<String> getOptions() {
List<String> res = new ArrayList<String>();
res.add("");
res.add(T1.VER);
res.add(T1.NOTVER);
return res;
}
@RequestMapping(value="/", method=RequestMethod.GET)
public String get(Model m) {
// get all data and save in request for use by JSP
m.addAttribute("data", DB.getAll());
// get options and save in request for JSP
m.addAttribute("options", getOptions());
// forward to test.jsp
return "test";
}
@RequestMapping(value="/", method=RequestMethod.POST)
public String post(@RequestParam("f1") String f1, @RequestParam("f2") String f2, @RequestParam("f3") String f3, Model m) {
// store in database
DB.saveOne(new T1(Integer.parseInt(f1), f2, f3));
// get all data and save in request for use by JSP
m.addAttribute("data", DB.getAll());
// get options and save in request for JSP
m.addAttribute("options", getOptions());
// forward to test.jsp
return "test";
}
}
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
web.xml (configure web application):
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- define servlet -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- map servlet to everything -->
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring-servlet.xml (configure Spring MVC):
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:context = "http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="demo" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
Note that name of Spring config files is Spring-<servlet name in web.xml>.xml.
Packaging of war file:
0 Fri Dec 02 12:53:40 EST 2022 META-INF/ 109 Fri Dec 02 12:53:38 EST 2022 META-INF/MANIFEST.MF 0 Fri Dec 02 12:53:40 EST 2022 WEB-INF/ 680 Thu Nov 24 19:13:44 EST 2022 WEB-INF/web.xml 0 Fri Dec 02 12:53:40 EST 2022 WEB-INF/classes/ 0 Fri Dec 02 12:53:40 EST 2022 WEB-INF/classes/demo/ 762 Fri Dec 02 12:53:40 EST 2022 WEB-INF/classes/demo/DB.class 746 Fri Dec 02 12:53:40 EST 2022 WEB-INF/classes/demo/T1.class 1541 Fri Dec 02 12:53:40 EST 2022 WEB-INF/classes/demo/TestController.class 0 Fri Dec 02 12:53:40 EST 2022 WEB-INF/lib/ 368839 Thu Nov 15 15:09:06 EST 2018 WEB-INF/lib/spring-aop-5.1.2.RELEASE.jar 47352 Thu Nov 15 15:09:14 EST 2018 WEB-INF/lib/spring-aspects-5.1.2.RELEASE.jar 671376 Thu Nov 15 15:09:16 EST 2018 WEB-INF/lib/spring-beans-5.1.2.RELEASE.jar 1099343 Thu Nov 15 15:09:30 EST 2018 WEB-INF/lib/spring-context-5.1.2.RELEASE.jar 1289379 Thu Nov 15 15:09:56 EST 2018 WEB-INF/lib/spring-core-5.1.2.RELEASE.jar 280041 Thu Nov 15 15:10:10 EST 2018 WEB-INF/lib/spring-expression-5.1.2.RELEASE.jar 1375184 Thu Nov 15 15:11:02 EST 2018 WEB-INF/lib/spring-web-5.1.2.RELEASE.jar 798872 Thu Nov 15 15:11:36 EST 2018 WEB-INF/lib/spring-webmvc-5.1.2.RELEASE.jar 0 Fri Nov 25 19:42:20 EST 2022 WEB-INF/jsp/ 821 Fri Nov 25 19:42:20 EST 2022 WEB-INF/jsp/test.jsp 740 Thu Nov 24 19:11:42 EST 2022 WEB-INF/spring-servlet.xml
The result looks like:
test.jsp (view):
<%@ page language="java" %>
<%@ page contentType="text/html" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<title>Spring with JSP and Spring form</title>
</head>
<body>
<h1>Spring with JSP and Spring form</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<c:forEach items="${data}" var="o">
<tr>
<td><c:out value="${o.f1}"/></td>
<td><c:out value="${o.f2}"/></td>
<td><c:out value="${o.f3}"/></td>
</tr>
</c:forEach>
</table>
<h2>Add data:</h2>
<form:form method="post" modelAttribute="addForm">
F1: <form:input path="f1"/>
<br>
F2: <form:input path="f2"/>
<br>
F3: <form:select path="f3" items="${options}"/>
<br>
<input type="submit" value="Add"/>
</form:form>
</body>
</html>
TestController.java (controller):
package demo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class TestController {
// options
private List<String> getOptions() {
List<String> res = new ArrayList<String>();
res.add("");
res.add(T1.VER);
res.add(T1.NOTVER);
return res;
}
@RequestMapping(value="/", method=RequestMethod.GET)
public String get(Model m) {
// setup empty form data
m.addAttribute("addForm", new AddForm());
// get all data and save in request for use by JSP
m.addAttribute("data", DB.getAll());
// get options and save in request for JSP
m.addAttribute("options", getOptions());
// forward to test.jsp
return "test";
}
@RequestMapping(value="/", method=RequestMethod.POST)
public String post(@ModelAttribute("addForm") AddForm addfrm, Model m) {
// get form data
int f1 = Integer.parseInt(addfrm.getF1());
String f2 = addfrm.getF2();
String f3 = addfrm.getF3();
// store in database
DB.saveOne(new T1(f1, f2, f3));
// get all data and save in request for use by JSP
m.addAttribute("data", DB.getAll());
// get options and save in request for JSP
m.addAttribute("options", getOptions());
// forward to test.jsp
return "test";
}
}
AddForm.java (form data to add):
package demo;
// form submit data
public class AddForm {
private String f1;
private String f2;
private String f3;
public AddForm() {
this("", "", "");
}
public AddForm(String f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public String getF1() {
return f1;
}
public void setF1(String f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
web.xml (configuration of web application):
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- define servlet -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- map servlet to everything -->
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring-servlet.xml (configuration of Spring MVC):
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:context = "http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="demo" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
Note that name of Spring config files is Spring-<servlet name in web.xml>.xml.
Packaging of war file:
0 Fri Dec 02 13:12:12 EST 2022 META-INF/ 109 Fri Dec 02 13:12:10 EST 2022 META-INF/MANIFEST.MF 0 Fri Dec 02 13:12:12 EST 2022 WEB-INF/ 680 Thu Nov 24 19:13:44 EST 2022 WEB-INF/web.xml 0 Fri Dec 02 13:12:12 EST 2022 WEB-INF/classes/ 0 Fri Dec 02 13:12:12 EST 2022 WEB-INF/classes/demo/ 629 Fri Dec 02 13:12:12 EST 2022 WEB-INF/classes/demo/AddForm.class 762 Fri Dec 02 13:12:12 EST 2022 WEB-INF/classes/demo/DB.class 746 Fri Dec 02 13:12:12 EST 2022 WEB-INF/classes/demo/T1.class 1612 Fri Dec 02 13:12:12 EST 2022 WEB-INF/classes/demo/TestController.class 0 Fri Dec 02 13:12:12 EST 2022 WEB-INF/lib/ 368839 Thu Nov 15 15:09:06 EST 2018 WEB-INF/lib/spring-aop-5.1.2.RELEASE.jar 47352 Thu Nov 15 15:09:14 EST 2018 WEB-INF/lib/spring-aspects-5.1.2.RELEASE.jar 671376 Thu Nov 15 15:09:16 EST 2018 WEB-INF/lib/spring-beans-5.1.2.RELEASE.jar 1099343 Thu Nov 15 15:09:30 EST 2018 WEB-INF/lib/spring-context-5.1.2.RELEASE.jar 1289379 Thu Nov 15 15:09:56 EST 2018 WEB-INF/lib/spring-core-5.1.2.RELEASE.jar 280041 Thu Nov 15 15:10:10 EST 2018 WEB-INF/lib/spring-expression-5.1.2.RELEASE.jar 1375184 Thu Nov 15 15:11:02 EST 2018 WEB-INF/lib/spring-web-5.1.2.RELEASE.jar 798872 Thu Nov 15 15:11:36 EST 2018 WEB-INF/lib/spring-webmvc-5.1.2.RELEASE.jar 0 Fri Nov 25 19:42:36 EST 2022 WEB-INF/jsp/ 867 Fri Nov 25 19:42:36 EST 2022 WEB-INF/jsp/test.jsp 740 Thu Nov 24 19:11:42 EST 2022 WEB-INF/spring-servlet.xml
The result looks like:
Thymeleaf is a new template engine (version 1.0 is from 2011) that can be used by Spring MVC instead of JSP.
Thymeleaf is valid XHTML just with some extra attributes.
In theory that makes it possible for HTML designers to work with the pages offline.
test.html (view):
<html xmlns:th="https://thymeleaf.org">
<head>
<title>Spring with Thymeleaf</title>
</head>
<body>
<h1>Spring with Thymeleaf</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<tr th:each="o: ${data}">
<td th:text="${o.f1}"/>
<td th:text="${o.f2}"/>
<td th:text="${o.f3}"/>
</tr>
</table>
<h2>Add data:</h2>
<form method="post" th:object="${addForm}">
F1: <input type="text" name="f1" th:field="*{f1}"/>
<br>
F2: <input type="text" name="f2" th:field="*{f2}"/>
<br>
F3: <select name="f3" th:field="*{f3}" items="${options}">
<option th:each="opt: ${options}" th:value="${opt}" th:text="${opt}"/>
</select>
<br>
<input type="submit" value="Add"/>
</form>
</body>
</html>
TestController.java (controller):
package demo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class TestController {
// options
private List<String> getOptions() {
List<String> res = new ArrayList<String>();
res.add("");
res.add(T1.VER);
res.add(T1.NOTVER);
return res;
}
@RequestMapping(value="/", method=RequestMethod.GET)
public String get(Model m) {
// setup empty form data
m.addAttribute("addForm", new AddForm());
// get all data and save in request for use by JSP
m.addAttribute("data", DB.getAll());
// get options and save in request for JSP
m.addAttribute("options", getOptions());
// forward to test.jsp
return "test";
}
@RequestMapping(value="/", method=RequestMethod.POST)
public String post(@ModelAttribute("addForm") AddForm addfrm, Model m) {
// get form data
int f1 = Integer.parseInt(addfrm.getF1());
String f2 = addfrm.getF2();
String f3 = addfrm.getF3();
// store in database
DB.saveOne(new T1(f1, f2, f3));
// get all data and save in request for use by JSP
m.addAttribute("data", DB.getAll());
// get options and save in request for JSP
m.addAttribute("options", getOptions());
// forward to test.jsp
return "test";
}
}
AddForm.java (form data for add):
package demo;
// form submit data
public class AddForm {
private String f1;
private String f2;
private String f3;
public AddForm() {
this("", "", "");
}
public AddForm(String f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public String getF1() {
return f1;
}
public void setF1(String f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
T1.java (data class):
package demo;
import java.io.Serializable;
// data class (row in database)
public class T1 implements Serializable {
public static final String VER = "Verified";
public static final String NOTVER = "Not verified";
private int f1;
private String f2;
private String f3;
public T1() {
this(0, "", "");
}
public T1(int f1, String f2, String f3) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
}
public int getF1() {
return f1;
}
public void setF1(int f1) {
this.f1 = f1;
}
public String getF2() {
return f2;
}
public void setF2(String f2) {
this.f2 = f2;
}
public String getF3() {
return f3;
}
public void setF3(String f3) {
this.f3 = f3;
}
}
DB.java (simulated database):
package demo;
import java.util.ArrayList;
import java.util.List;
// simulated database
public class DB {
private static List<T1> db;
static {
db = new ArrayList<T1>();
db.add(new T1(1,"A", T1.VER));
db.add(new T1(2,"BB", T1.VER));
db.add(new T1(3,"CCC", T1.VER));
db.add(new T1(4,"DDDD", T1.VER));
db.add(new T1(5,"EEEEE", T1.NOTVER));
}
public static List<T1> getAll() {
return db;
}
public static void saveOne(T1 o) {
db.add(o);
}
}
web.xml (configuration of web application):
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- define servlet -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- map servlet to everything -->
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring-servlet.xml (configuration of Spring MVC and Thymeleaf):
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:context = "http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="demo" />
<bean id="templateResolver" class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/html/" />
<property name="suffix" value=".html" />
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
</bean>
<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
</bean>
</beans>
Packaging of war file:
0 Fri Dec 02 20:09:04 EST 2022 META-INF/ 109 Fri Dec 02 20:09:02 EST 2022 META-INF/MANIFEST.MF 0 Fri Dec 02 20:09:04 EST 2022 WEB-INF/ 680 Thu Nov 24 19:13:44 EST 2022 WEB-INF/web.xml 0 Fri Dec 02 20:09:04 EST 2022 WEB-INF/classes/ 0 Fri Dec 02 20:09:04 EST 2022 WEB-INF/classes/demo/ 629 Fri Dec 02 20:09:04 EST 2022 WEB-INF/classes/demo/AddForm.class 762 Fri Dec 02 20:09:04 EST 2022 WEB-INF/classes/demo/DB.class 746 Fri Dec 02 20:09:04 EST 2022 WEB-INF/classes/demo/T1.class 1612 Fri Dec 02 20:09:04 EST 2022 WEB-INF/classes/demo/TestController.class 0 Fri Dec 02 20:09:04 EST 2022 WEB-INF/lib/ 246390 Fri Nov 25 16:23:26 EST 2022 WEB-INF/lib/attoparser-2.0.6.RELEASE.jar 61409 Fri Nov 25 16:23:26 EST 2022 WEB-INF/lib/slf4j-api-2.0.3.jar 368839 Thu Nov 15 15:09:06 EST 2018 WEB-INF/lib/spring-aop-5.1.2.RELEASE.jar 47352 Thu Nov 15 15:09:14 EST 2018 WEB-INF/lib/spring-aspects-5.1.2.RELEASE.jar 671376 Thu Nov 15 15:09:16 EST 2018 WEB-INF/lib/spring-beans-5.1.2.RELEASE.jar 1099343 Thu Nov 15 15:09:30 EST 2018 WEB-INF/lib/spring-context-5.1.2.RELEASE.jar 1289379 Thu Nov 15 15:09:56 EST 2018 WEB-INF/lib/spring-core-5.1.2.RELEASE.jar 280041 Thu Nov 15 15:10:10 EST 2018 WEB-INF/lib/spring-expression-5.1.2.RELEASE.jar 1375184 Thu Nov 15 15:11:02 EST 2018 WEB-INF/lib/spring-web-5.1.2.RELEASE.jar 798872 Thu Nov 15 15:11:36 EST 2018 WEB-INF/lib/spring-webmvc-5.1.2.RELEASE.jar 936897 Fri Nov 25 16:23:02 EST 2022 WEB-INF/lib/thymeleaf-3.1.0.RELEASE.jar 47439 Fri Nov 25 16:23:04 EST 2022 WEB-INF/lib/thymeleaf-extras-springsecurity5-3.1.0.RELEASE.jar 186687 Fri Nov 25 16:23:02 EST 2022 WEB-INF/lib/thymeleaf-spring5-3.1.0.RELEASE.jar 173935 Fri Nov 25 16:23:26 EST 2022 WEB-INF/lib/unbescape-1.1.6.RELEASE.jar 0 Fri Nov 25 19:56:36 EST 2022 WEB-INF/html/ 743 Fri Nov 25 19:56:36 EST 2022 WEB-INF/html/test.html 1062 Fri Nov 25 19:16:50 EST 2022 WEB-INF/spring-servlet.xml
The result looks like:
For Spring Boot deployment just use Maven for directory structure and build the jar file.
Maven generated jar file:
0 Fri Dec 02 20:14:54 EST 2022 META-INF/ 528 Fri Dec 02 20:14:54 EST 2022 META-INF/MANIFEST.MF 0 Fri Dec 02 20:14:54 EST 2022 org/ 0 Fri Dec 02 20:14:54 EST 2022 org/springframework/ 0 Fri Dec 02 20:14:54 EST 2022 org/springframework/boot/ 0 Fri Dec 02 20:14:54 EST 2022 org/springframework/boot/loader/ 0 Fri Dec 02 20:14:54 EST 2022 org/springframework/boot/loader/data/ 2688 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/data/RandomAccessDataFile$DataInputStream.class 0 Fri Dec 02 20:14:54 EST 2022 org/springframework/boot/loader/jar/ 4976 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/jar/AsciiBytes.class 3263 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/data/RandomAccessDataFile$FileAccess.class 1593 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/jar/JarFileEntries$1.class 0 Fri Dec 02 20:14:54 EST 2022 org/springframework/boot/loader/archive/ 3837 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/archive/ExplodedArchive$FileEntryIterator.class 273 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/archive/ExplodedArchive$1.class 282 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/data/RandomAccessDataFile$1.class 2046 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/jar/JarFileEntries$EntryIterator.class 4015 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/data/RandomAccessDataFile.class 14087 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/jar/JarFileEntries.class 485 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/data/RandomAccessData.class 540 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/jar/CentralDirectoryVisitor.class 299 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/jar/JarEntryFilter.class 5243 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/archive/ExplodedArchive.class 1779 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/archive/JarFileArchive$EntryIterator.class 1081 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/archive/JarFileArchive$JarFileEntry.class 7336 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/archive/JarFileArchive.class 1953 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/PropertiesLauncher$PrefixMatchingArchiveFilter.class 1484 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/PropertiesLauncher$ArchiveEntryFilter.class 266 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/PropertiesLauncher$1.class 19737 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/PropertiesLauncher.class 4684 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/Launcher.class 1502 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/MainMethodRunner.class 3608 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/ExecutableArchiveLauncher.class 0 Fri Dec 02 20:14:54 EST 2022 org/springframework/boot/loader/util/ 5203 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/util/SystemPropertyUtils.class 616 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/jar/Bytes.class 1721 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/WarLauncher.class 1585 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/JarLauncher.class 1535 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/LaunchedURLClassLoader$UseFastConnectionExceptionsEnumeration.class 5699 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/LaunchedURLClassLoader.class 702 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/jar/JarURLConnection$1.class 5267 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/jar/CentralDirectoryFileHeader.class 4306 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/jar/JarURLConnection$JarEntryName.class 3116 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/jar/CentralDirectoryEndRecord.class 9854 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/jar/JarURLConnection.class 1813 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/jar/ZipInflaterInputStream.class 2062 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/jar/JarFile$1.class 4624 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/jar/CentralDirectoryParser.class 11949 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/jar/Handler.class 1233 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/jar/JarFile$2.class 1374 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/jar/JarFile$JarFileType.class 302 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/archive/Archive$Entry.class 15076 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/jar/JarFile.class 945 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/archive/Archive.class 3619 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/jar/JarEntry.class 437 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/archive/Archive$EntryFilter.class 345 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/jar/FileHeader.class 1487 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/archive/ExplodedArchive$FileEntryIterator$EntryComparator.class 3650 Sat Jan 12 02:33:04 EST 2019 org/springframework/boot/loader/jar/StringSequence.class 1102 Sat Jan 12 02:33:06 EST 2019 org/springframework/boot/loader/archive/ExplodedArchive$FileEntry.class 0 Fri Dec 02 20:14:54 EST 2022 BOOT-INF/ 0 Fri Dec 02 20:14:54 EST 2022 BOOT-INF/classes/ 0 Fri Dec 02 20:14:50 EST 2022 BOOT-INF/classes/demo/ 0 Wed Nov 30 10:02:52 EST 2022 BOOT-INF/classes/templates/ 0 Fri Dec 02 20:14:54 EST 2022 META-INF/maven/ 0 Fri Dec 02 20:14:54 EST 2022 META-INF/maven/org.springframework.boot/ 0 Fri Dec 02 20:14:54 EST 2022 META-INF/maven/org.springframework.boot/web-thymeleaf/ 1009 Fri Dec 02 20:14:50 EST 2022 BOOT-INF/classes/demo/DB.class 676 Fri Dec 02 20:14:50 EST 2022 BOOT-INF/classes/demo/Main.class 1131 Fri Dec 02 20:14:50 EST 2022 BOOT-INF/classes/demo/AddForm.class 1238 Fri Dec 02 20:14:50 EST 2022 BOOT-INF/classes/demo/T1.class 2222 Fri Dec 02 20:14:50 EST 2022 BOOT-INF/classes/demo/TestController.class 743 Wed Nov 30 10:02:52 EST 2022 BOOT-INF/classes/templates/test.html 2676 Wed Nov 30 09:58:40 EST 2022 META-INF/maven/org.springframework.boot/web-thymeleaf/pom.xml 105 Wed Nov 30 09:59:20 EST 2022 META-INF/maven/org.springframework.boot/web-thymeleaf/pom.properties 0 Fri Dec 02 20:14:54 EST 2022 BOOT-INF/lib/ 405 Sat Jan 12 02:46:54 EST 2019 BOOT-INF/lib/spring-boot-starter-web-2.1.2.RELEASE.jar 399 Sat Jan 12 02:46:36 EST 2019 BOOT-INF/lib/spring-boot-starter-2.1.2.RELEASE.jar 407 Sat Jan 12 02:46:36 EST 2019 BOOT-INF/lib/spring-boot-starter-logging-2.1.2.RELEASE.jar 290339 Fri Mar 31 21:27:54 EDT 2017 BOOT-INF/lib/logback-classic-1.2.3.jar 471901 Fri Mar 31 21:27:16 EDT 2017 BOOT-INF/lib/logback-core-1.2.3.jar 17524 Sun Jul 22 20:47:34 EDT 2018 BOOT-INF/lib/log4j-to-slf4j-2.11.1.jar 264060 Sun Jul 22 20:44:36 EDT 2018 BOOT-INF/lib/log4j-api-2.11.1.jar 4596 Thu Mar 16 17:37:48 EDT 2017 BOOT-INF/lib/jul-to-slf4j-1.7.25.jar 26586 Wed Feb 21 15:54:16 EST 2018 BOOT-INF/lib/javax.annotation-api-1.3.2.jar 301298 Mon Aug 27 16:23:36 EDT 2018 BOOT-INF/lib/snakeyaml-1.23.jar 405 Sat Jan 12 02:46:54 EST 2019 BOOT-INF/lib/spring-boot-starter-json-2.1.2.RELEASE.jar 1347236 Sat Dec 15 21:59:06 EST 2018 BOOT-INF/lib/jackson-databind-2.9.8.jar 66519 Sat Jul 29 20:53:26 EDT 2017 BOOT-INF/lib/jackson-annotations-2.9.0.jar 325619 Sat Dec 15 13:19:12 EST 2018 BOOT-INF/lib/jackson-core-2.9.8.jar 33391 Sat Dec 15 23:06:14 EST 2018 BOOT-INF/lib/jackson-datatype-jdk8-2.9.8.jar 100674 Sat Dec 15 23:06:24 EST 2018 BOOT-INF/lib/jackson-datatype-jsr310-2.9.8.jar 8642 Sat Dec 15 23:06:04 EST 2018 BOOT-INF/lib/jackson-module-parameter-names-2.9.8.jar 406 Sat Jan 12 02:46:54 EST 2019 BOOT-INF/lib/spring-boot-starter-tomcat-2.1.2.RELEASE.jar 3252651 Thu Dec 06 21:15:22 EST 2018 BOOT-INF/lib/tomcat-embed-core-9.0.14.jar 249920 Thu Dec 06 21:15:24 EST 2018 BOOT-INF/lib/tomcat-embed-el-9.0.14.jar 263169 Thu Dec 06 21:15:24 EST 2018 BOOT-INF/lib/tomcat-embed-websocket-9.0.14.jar 1155701 Fri Jan 04 14:52:48 EST 2019 BOOT-INF/lib/hibernate-validator-6.0.14.Final.jar 93107 Tue Dec 19 16:23:28 EST 2017 BOOT-INF/lib/validation-api-2.0.1.Final.jar 66469 Wed Feb 14 13:23:28 EST 2018 BOOT-INF/lib/jboss-logging-3.3.2.Final.jar 66540 Tue Mar 27 18:35:34 EDT 2018 BOOT-INF/lib/classmate-1.4.0.jar 1381418 Wed Jan 09 12:25:20 EST 2019 BOOT-INF/lib/spring-web-5.1.4.RELEASE.jar 672301 Wed Jan 09 12:24:30 EST 2019 BOOT-INF/lib/spring-beans-5.1.4.RELEASE.jar 800394 Wed Jan 09 12:26:00 EST 2019 BOOT-INF/lib/spring-webmvc-5.1.4.RELEASE.jar 368931 Wed Jan 09 12:24:44 EST 2019 BOOT-INF/lib/spring-aop-5.1.4.RELEASE.jar 1099300 Wed Jan 09 12:24:52 EST 2019 BOOT-INF/lib/spring-context-5.1.4.RELEASE.jar 280284 Wed Jan 09 12:24:46 EST 2019 BOOT-INF/lib/spring-expression-5.1.4.RELEASE.jar 409 Sat Jan 12 02:47:12 EST 2019 BOOT-INF/lib/spring-boot-starter-thymeleaf-2.1.2.RELEASE.jar 177164 Sun Oct 28 22:43:38 EDT 2018 BOOT-INF/lib/thymeleaf-spring5-3.0.11.RELEASE.jar 869740 Sun Oct 28 22:35:36 EDT 2018 BOOT-INF/lib/thymeleaf-3.0.11.RELEASE.jar 244959 Fri Mar 30 09:34:24 EDT 2018 BOOT-INF/lib/attoparser-2.0.5.RELEASE.jar 173935 Fri Mar 30 17:04:26 EDT 2018 BOOT-INF/lib/unbescape-1.1.6.RELEASE.jar 41203 Thu Mar 16 17:36:32 EDT 2017 BOOT-INF/lib/slf4j-api-1.7.25.jar 39885 Tue Nov 27 21:19:34 EST 2018 BOOT-INF/lib/thymeleaf-extras-java8time-3.0.2.RELEASE.jar 1293220 Wed Jan 09 12:24:24 EST 2019 BOOT-INF/lib/spring-core-5.1.4.RELEASE.jar 23724 Wed Jan 09 12:24:14 EST 2019 BOOT-INF/lib/spring-jcl-5.1.4.RELEASE.jar 948314 Sat Jan 12 02:17:22 EST 2019 BOOT-INF/lib/spring-boot-2.1.2.RELEASE.jar 1256089 Sat Jan 12 02:26:00 EST 2019 BOOT-INF/lib/spring-boot-autoconfigure-2.1.2.RELEASE.jar 1142180 Sat Dec 29 21:04:18 EST 2018 BOOT-INF/lib/bootstrap-4.2.1.jar 164927 Fri Jun 10 10:33:04 EDT 2016 BOOT-INF/lib/jquery-3.0.0.jar 445320 Wed Aug 01 08:36:28 EDT 2018 BOOT-INF/lib/popper.js-1.14.3.jar
The result looks like:
Grails is a Groovy based RoR Style web application framework.
Name and creator | Grails is an open source web application framework created by Graeme Rocher |
History | Version 0.1 in 2006 Version 1.0 in 2008 |
Programming language | Groovy |
View technology | GSP (Groovy Server Pages) |
Deployment | Servlet container Standalone |
Other technical characteristics | |
Status | Actively maintained with small but loyal community |
Grails is a very traditional MVC framework with multiple controllers each with muiltiple actions and an action can either forward to a view or redirect to an URL.
Generation command:
grails create-app test
cd test
grails create-controller test
Run standalone command:
cd test
grails run-app --info
Create war command:
cd test
grails war
grails-app/controllers/test/TestController.groovy (controller):
package test
class TestController {
def index() {
[data: DB.getAll(), options: ["", T1.VER, T1.NOTVER]]
}
def add() {
DB.saveOne(new T1(f1: Integer.parseInt(params.f1), f2: params.f2, f3: params.f3))
redirect(action: "index")
}
}
grails-app/domain/test/TestModel.groovy (model, simulated database):
package test
class T1 {
static String VER = "Verified"
static String NOTVER = "Not verified"
int f1
String f2
String f3
}
class DB {
static
db = [ new T1(f1: 1, f2: "A", f3: T1.VER),
new T1(f1: 2, f2: "BB", f3: T1.VER),
new T1(f1: 3, f2: "CCC", f3: T1.VER),
new T1(f1: 4, f2: "DDDD", f3: T1.VER),
new T1(f1: 5, f2: "EEEEE", f3: T1.NOTVER)]
static getAll() {
return db
}
static saveOne(T1 o) {
db.add(o)
}
}
grails-app/views/test/index.gsp (view):
<html>
<head>
<title>Grails</title>
</head>
<body>
<h1>Grails</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<g:each in="${data}" var="o">
<tr>
<td>${o.f1}</td>
<td>${o.f2}</td>
<td>${o.f3}</td>
</tr>
</g:each>
</table>
<h2>Add data:</h2>
<form method="post" action="/test/add">
F1: <input type="text" name="f1">
<br>
F2: <input type="text" name="f2">
<br>
F3: <select name="f3">
<g:each in="${options}" var="opt">
<option>${opt}</option>
</g:each>
</select>
<br>
<input type="submit" value="Add"/>
</form>
</body>
</html>
The result looks like:
grails-app/views/test/index.gsp (view):
<html>
<head>
<title>Grails - grails form</title>
</head>
<body>
<h1>Grails - grails form</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<g:each in="${data}" var="o">
<tr>
<td>${o.f1}</td>
<td>${o.f2}</td>
<td>${o.f3}</td>
</tr>
</g:each>
</table>
<h2>Add data:</h2>
<g:form url="[controller:'test',action:'add']">
F1: <g:textField name="f1"/>
<br>
F2: <g:textField name="f2"/>
<br>
F3: <g:select name="f3" from="${options}"/>
<br>
<g:actionSubmit value="Add"/>
</g:form>
</body>
</html>
The result looks like:
ASP.NET MVC has replaced ASP.NET Web Forms as the .NET primary web application framework.
Name and creator | ASP.NET MVC / Microsoft |
History | Version 1.0 in 2009 Version 3.0 in 2011 Version 5.0 in 2013 |
Programming language | C# VB.NET |
View technology | ASPX Razor |
Deployment | IIS |
Other technical characteristics | |
Status | Obsolete with .NET 5.0 in 2020 |
ASP.NET MVC is very traditional MVC with a controller forwarding to a view - ASPX or Razor.
TestController.cs (controller):
using System;
using System.Web.Mvc;
namespace Demo.Controllers
{
public class TestController : Controller
{
public ActionResult List()
{
return View(DB.GetAll());
}
public ActionResult Add(FormCollection frmcol)
{
string f1 = (string)frmcol["f1"];
string f2 = (string)frmcol["f2"];
string f3 = (string)frmcol["f3"];
DB.SaveOne(new T1 { F1 = int.Parse(f1), F2 = f2, F3 = f3 });
return RedirectToAction("List");
}
}
}
DB.cs (simulated database):
using System;
using System.Collections.Generic;
namespace Demo
{
// data class (row in database)
public class T1
{
public const String VER = "Verified";
public const String NOTVER = "Not verified";
public int F1 { get; set; }
public string F2 { get; set; }
public string F3 { get; set; }
}
// simulated database
public class DB
{
private static IList<T1> db;
static DB()
{
db = new List<T1>();
db.Add(new T1 { F1 = 1, F2 = "A", F3 = T1.VER });
db.Add(new T1 { F1 = 2, F2 = "BB", F3 = T1.VER });
db.Add(new T1 { F1 = 3, F2 = "CCC", F3 = T1.VER });
db.Add(new T1 { F1 = 4, F2 = "DDDD", F3 = T1.VER });
db.Add(new T1 { F1 = 5, F2 = "EEEEE", F3 = T1.NOTVER });
}
public static IList<T1> GetAll()
{
return db;
}
public static void SaveOne(T1 o)
{
db.Add(o);
}
}
}
Util.cs (option list):
using System;
using System.Web.Mvc;
namespace Demo
{
public static class Util
{
public static SelectListItem[] GetOptions()
{
return new SelectListItem[] { new SelectListItem { Text = "", Value = "" },
new SelectListItem { Text = T1.VER, Value = T1.VER },
new SelectListItem { Text = T1.NOTVER, Value = T1.NOTVER } };
}
}
}
Global.asax (configuration of web application - just referencing TestApplication class):
<%@ Application Inherits="Demo.TestApplication" %>
TestApplication.cs (real configuration of web application):
using System;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
namespace Demo
{
public class TestApplication : HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.Ignore("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new {
controller = "Test",
action = "List",
id = UrlParameter.Optional
});
}
protected void Application_Start()
{
ViewEngines.Engines.Add(new RazorViewEngine());
RegisterRoutes(RouteTable.Routes);
}
}
}
It is really just setting up the route to the controller.
What to add to web.config somewhat depends on the software installed, but I had to add this fragment:
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor" requirePermission="false"/>
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor" requirePermission="false"/>
</sectionGroup>
</configSections>
<system.web>
<compilation debug="true" targetFramework="4.5">
<assemblies>
<add assembly="System.Web.Mvc"/>
</assemblies>
</compilation>
<pages>
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Html"/>
</namespaces>
</pages>
<httpRuntime targetFramework="4.5" />
</system.web>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc"/>
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
</system.web.webPages.razor>
The C# code either has to be placed in App_code dir or be compiled to a DLL and placed in bind ir.
The views has to exist as Views\<controller name>\<action name name><view type extenstion>.
List.aspx (view):
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="Demo" %>
<html>
<head>
<title>ASP.NET MVC with ASPX view</title>
</head>
<body>
<h1>ASP.NET MVC with ASPX view</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
<%
foreach(T1 o in (List<T1>)Model) {
%>
<tr>
<td><%=o.F1%></td>
<td><%=o.F2%></td>
<td><%=o.F3%></td>
</tr>
<%
}
%>
</table>
<h2>Add data:</h2>
<% using(Html.BeginForm("Add", "Test", FormMethod.Post)) { %>
F1: <%= Html.TextBox("f1") %>
<br/>
F2: <%= Html.TextBox("f2") %>
<br/>
F3: <%= Html.DropDownList("f3", Util.GetOptions()) %>
<br/>
<input type="submit" value="Add"/>
<% } %>
</body>
</html>
It is simple - <% %> around code blocks, <%= %> for values and some Html helper function. Very similar to ASP Classic!
The result looks like:
List.cshtml (view):
@using System.Collections.Generic
@using Demo
@model List<T1>
<html>
<head>
<title>ASP.NET MVC with Razor view</title>
</head>
<body>
<h1>ASP.NET MVC with Razor view</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
@foreach(T1 o in Model) {
<tr>
<td>@o.F1</td>
<td>@o.F2</td>
<td>@o.F3</td>
</tr>
}
</table>
<h2>Add data:</h2>
@using(Html.BeginForm("Add", "Test", FormMethod.Post)) {
<text>
F1: @Html.TextBox("f1")
<br/>
F2: @Html.TextBox("f2")
<br/>
F3: @Html.DropDownList("f3", Util.GetOptions())
<br/>
<input type="submit" value="Add"/>
</text>
}
</body>
</html>
It is very simple - HTML and C# are just mixed and C# is prefixed with @ to mark it as C#.
The text tag inside the form is required - otherwise the Fn: gets interpreted as C# resulting in a compilation error!
The result looks like:
ASP.NET Core MVC is the successor of ASP.NET MVC.
And it is 99% compatible with it.
Name and creator | ASP.NET Core MVC / Microsoft |
History | Version 1.0 in 2016 Version 3.0 in 2019 |
Programming language | C# |
View technology | Razor |
Deployment | ASP.NET Core Kestrel engine |
Other technical characteristics | |
Status | Actively maintained |
List.cshtml (view):
@using System.Collections.Generic
@using Demo
@model List<T1>
<html>
<head>
<title>ASP.NET Core MVC</title>
</head>
<body>
<h1>ASP.NET Core MVC</h1>
<h2>Show data:</h2>
<table border="1">
<tr>
<th>F1</th>
<th>F2</th>
<th>F3</th>
</tr>
@foreach(T1 o in Model) {
<tr>
<td>@o.F1</td>
<td>@o.F2</td>
<td>@o.F3</td>
</tr>
}
</table>
<h2>Add data:</h2>
@using(Html.BeginForm("Add", "Test", FormMethod.Post)) {
<text>
F1: @Html.TextBox("f1")
<br/>
F2: @Html.TextBox("f2")
<br/>
F3: @Html.DropDownList("f3", Util.GetOptions())
<br/>
<input type="submit" value="Add"/>
</text>
}
</body>
</html>
It is very simple - HTML and C# are just mixed and C# is prefixed with @ to mark it as C#.
The text tag inside the form is required - otherwise the Fn: gets interpreted as C# resulting in a compilation error!
TestController.cs (controller):
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Demo.Controllers
{
public class TestController : Controller
{
public ActionResult List()
{
return View(DB.GetAll());
}
public ActionResult Add(IFormCollection frmcol)
{
string f1 = (string)frmcol["f1"];
string f2 = (string)frmcol["f2"];
string f3 = (string)frmcol["f3"];
DB.SaveOne(new T1 { F1 = int.Parse(f1), F2 = f2, F3 = f3 });
return RedirectToAction("List");
}
}
}
The code is fundamentally the same as for ASP.NET MVC, but the namespaces are different and it is IFormCollection instead of FormCollection.
DB.cs (simulated database):
using System;
using System.Collections.Generic;
namespace Demo
{
// data class (row in database)
public class T1
{
public const String VER = "Verified";
public const String NOTVER = "Not verified";
public int F1 { get; set; }
public string F2 { get; set; }
public string F3 { get; set; }
}
// simulated database
public class DB
{
private static IList<T1> db;
static DB()
{
db = new List<T1>();
db.Add(new T1 { F1 = 1, F2 = "A", F3 = T1.VER });
db.Add(new T1 { F1 = 2, F2 = "BB", F3 = T1.VER });
db.Add(new T1 { F1 = 3, F2 = "CCC", F3 = T1.VER });
db.Add(new T1 { F1 = 4, F2 = "DDDD", F3 = T1.VER });
db.Add(new T1 { F1 = 5, F2 = "EEEEE", F3 = T1.NOTVER });
}
public static IList<T1> GetAll()
{
return db;
}
public static void SaveOne(T1 o)
{
db.Add(o);
}
}
}
Util.cs (option list):
using System;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace Demo
{
public static class Util
{
public static SelectListItem[] GetOptions()
{
return new SelectListItem[] { new SelectListItem { Text = "", Value = "" },
new SelectListItem { Text = T1.VER, Value = T1.VER },
new SelectListItem { Text = T1.NOTVER, Value = T1.NOTVER } };
}
}
}
Again same just different namespace compared to ASP.NET MVC.
Program.cs (main program):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Demo
{
public class Program
{
public static void Main(string[] args)
{
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(b =>
{
b.UseStartup<Startup>();
}).Build().Run();
}
}
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(ep =>
{
ep.MapControllerRoute(name: "default",
pattern: "{controller=Test}/{action=List}/{id?}");
});
}
}
}
Basically just setup routing to the controller.
An ASP.NET Core MVC project can be created command line with:
dotnet new webapp
The result looks like:
Version | Date | Description |
---|---|---|
1.0 | December 3rd 2022 | Initial version |
1.1 | December 6th 2022 | Add Struts 2.x section |
1.2 | May 23rd 2023 | Add Stripes section |
1.3 | January 15th 2024 | Add Grails section |
See list of all articles here
Please send comments to Arne Vajhøj